├── .gitignore ├── MANIFEST.in ├── examples ├── client.py ├── server.py ├── server2.py └── client2.py ├── LICENSE.md ├── README.md ├── python2 └── hprose │ ├── common.py │ ├── __init__.py │ ├── client.py │ ├── httpserver.py │ ├── httpclient.py │ ├── server.py │ └── io.py ├── python3 ├── hprose │ ├── common.py │ ├── __init__.py │ ├── client.py │ ├── httpserver.py │ ├── httpclient.py │ ├── server.py │ └── io.py └── fpconst │ └── __init__.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | MANIFEST 2 | dist 3 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.md 2 | recursive-include python2 * 3 | recursive-include python3 * 4 | recursive-include examples * 5 | -------------------------------------------------------------------------------- /examples/client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import hprose 5 | 6 | def main(): 7 | client = hprose.HttpClient('http://127.0.0.1:8181/') 8 | print(client.hello("World")) 9 | 10 | if __name__ == '__main__': 11 | main() 12 | -------------------------------------------------------------------------------- /examples/server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import hprose 5 | 6 | def hello(name): 7 | return 'Hello %s!' % name 8 | 9 | def main(): 10 | server = hprose.HttpServer(port = 8181) 11 | server.addFunction(hello) 12 | server.start() 13 | 14 | if __name__ == '__main__': 15 | main() 16 | -------------------------------------------------------------------------------- /examples/server2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import hprose 5 | 6 | def send_data(data): 7 | print(data) 8 | return data 9 | 10 | def main(): 11 | server = hprose.HttpServer(port = 8181) 12 | server.debug = True 13 | server.addFunction(send_data) 14 | server.start() 15 | 16 | if __name__ == '__main__': 17 | main() 18 | -------------------------------------------------------------------------------- /examples/client2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import hprose 5 | 6 | class MyFilter(object): 7 | def inputFilter(self, data, context): 8 | print(data) 9 | return data 10 | def outputFilter(self, data, context): 11 | print(data) 12 | return data 13 | 14 | def main(): 15 | client = hprose.HttpClient('http://127.0.0.1:8181/') 16 | client.filter = MyFilter() 17 | print(client.send_data({"Mon": 1, "Tue": 2, "Wed": { "i1": "Wed", "i2": 5} })) 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2008-2016 http://hprose.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hprose for Python 2 | 3 | [![Join the chat at https://gitter.im/hprose/hprose-python](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hprose/hprose-python?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | *Hprose* is a High Performance Remote Object Service Engine. 6 | 7 | It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system. 8 | 9 | *Hprose* supports many programming languages, for example: 10 | 11 | * AAuto Quicker 12 | * ActionScript 13 | * ASP 14 | * C++ 15 | * Dart 16 | * Delphi/Free Pascal 17 | * dotNET(C#, Visual Basic...) 18 | * Golang 19 | * Java 20 | * JavaScript 21 | * Node.js 22 | * Objective-C 23 | * Perl 24 | * PHP 25 | * Python 26 | * Ruby 27 | * ... 28 | 29 | Through *Hprose*, You can conveniently and efficiently intercommunicate between those programming languages. 30 | 31 | This project is the implementation of Hprose for Python. 32 | -------------------------------------------------------------------------------- /python2/hprose/common.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/common.py # 13 | # # 14 | # hprose common for python 2.3+ # 15 | # # 16 | # LastModified: Mar 19, 2014 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | class HproseResultMode: 22 | Normal = 0 23 | Serialized = 1 24 | Raw = 2 25 | RawWithEndTag = 3 26 | 27 | class HproseException(Exception): 28 | pass 29 | 30 | class HproseFilter(object): 31 | def inputFilter(self, data, context): 32 | return data; 33 | def outputFilter(self, data, context): 34 | return data; -------------------------------------------------------------------------------- /python3/hprose/common.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/common.py # 13 | # # 14 | # hprose common for python 3.0+ # 15 | # # 16 | # LastModified: Apr 12, 2014 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | class HproseResultMode: 22 | Normal = 0 23 | Serialized = 1 24 | Raw = 2 25 | RawWithEndTag = 3 26 | 27 | class HproseException(Exception): 28 | pass 29 | 30 | class HproseFilter(object): 31 | def inputFilter(self, data, context): 32 | return data; 33 | def outputFilter(self, data, context): 34 | return data; -------------------------------------------------------------------------------- /python2/hprose/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/__init__.py # 13 | # # 14 | # hprose for python 2.3+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | from hprose.common import HproseResultMode, HproseException 22 | from hprose.io import HproseTags, HproseClassManager, HproseRawReader, HproseReader, HproseWriter, HproseFormatter 23 | from hprose.client import HproseClient 24 | from hprose.server import HproseService 25 | from hprose.httpclient import HproseHttpClient 26 | from hprose.httpserver import HproseHttpService, HproseHttpServer, UrlMapMiddleware 27 | 28 | ResultMode = HproseResultMode 29 | Tags = HproseTags 30 | ClassManager = HproseClassManager 31 | RawReader = HproseRawReader 32 | Reader = HproseReader 33 | Writer = HproseWriter 34 | Formatter = HproseFormatter 35 | serialize = Formatter.serialize 36 | unserialize = Formatter.unserialize 37 | Client = HproseClient 38 | Service = HproseService 39 | HttpClient = HproseHttpClient 40 | HttpService = HproseHttpService 41 | HttpServer = HproseHttpServer 42 | -------------------------------------------------------------------------------- /python3/hprose/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/__init__.py # 13 | # # 14 | # hprose for python 3.0+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | from hprose.common import HproseResultMode, HproseException 22 | from hprose.io import HproseTags, HproseClassManager, HproseRawReader, HproseReader, HproseWriter, HproseFormatter 23 | from hprose.client import HproseClient 24 | from hprose.server import HproseService 25 | from hprose.httpclient import HproseHttpClient 26 | from hprose.httpserver import HproseHttpService, HproseHttpServer, UrlMapMiddleware 27 | 28 | ResultMode = HproseResultMode 29 | Tags = HproseTags 30 | ClassManager = HproseClassManager 31 | RawReader = HproseRawReader 32 | Reader = HproseReader 33 | Writer = HproseWriter 34 | Formatter = HproseFormatter 35 | serialize = Formatter.serialize 36 | unserialize = Formatter.unserialize 37 | Client = HproseClient 38 | Service = HproseService 39 | HttpClient = HproseHttpClient 40 | HttpService = HproseHttpService 41 | HttpServer = HproseHttpServer 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from distutils.core import setup 3 | if sys.version_info < (2, 3): 4 | print >> sys.stderr, 'error: python 2.3 or higher is required, you are using %s' %'.'.join([str(i) for i in sys.version_info]) 5 | 6 | sys.exit(1) 7 | 8 | args = dict( 9 | name = 'hprose', 10 | version = '1.4.3', 11 | description = 'Hprose is a High Performance Remote Object Service Engine.', 12 | long_description = open('README.md').read(), 13 | keywords = "hprose rpc serialize wsgi web service server development rest webservice json", 14 | author = 'Ma Bingyao', 15 | author_email = 'andot@hprose.com', 16 | url = 'https://github.com/hprose/hprose-python', 17 | license = 'MIT', 18 | platforms = 'any') 19 | 20 | if sys.version_info < (3, 0): 21 | args['install_requires'] = ['fpconst'] 22 | args['packages'] = ["hprose"] 23 | args['package_dir'] = dict(hprose = "python2/hprose") 24 | else: 25 | args['packages'] = ["hprose", 'fpconst'] 26 | args['package_dir'] = dict( 27 | hprose = "python3/hprose", 28 | fpconst = "python3/fpconst") 29 | 30 | args['classifiers'] = [ 31 | 'Development Status :: 5 - Production/Stable', 32 | 'Intended Audience :: Developers', 33 | 'Programming Language :: Python :: 2', 34 | 'Programming Language :: Python :: 2.3', 35 | 'Programming Language :: Python :: 2.4', 36 | 'Programming Language :: Python :: 2.5', 37 | 'Programming Language :: Python :: 2.6', 38 | 'Programming Language :: Python :: 2.7', 39 | 'Programming Language :: Python :: 3', 40 | 'Programming Language :: Python :: 3.0', 41 | 'Programming Language :: Python :: 3.1', 42 | 'Programming Language :: Python :: 3.2', 43 | 'Programming Language :: Python :: 3.3', 44 | 'Programming Language :: Python :: 3.4', 45 | 'License :: OSI Approved :: MIT License', 46 | 'Topic :: Internet', 47 | 'Topic :: Internet :: WWW/HTTP :: WSGI', 48 | 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', 49 | 'Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware', 50 | 'Topic :: Software Development :: Libraries :: Python Modules', 51 | 'Topic :: Software Development :: Object Brokering', 52 | 'Topic :: System :: Networking', 53 | 'Topic :: System :: Distributed Computing'] 54 | 55 | setup(**args) 56 | -------------------------------------------------------------------------------- /python3/fpconst/__init__.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.com/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # fpconst.py # 13 | # # 14 | # fpconst for python 3.0+ # 15 | # # 16 | # LastModified: May 16, 2010 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | # This python module implements constants and functions for 22 | # working with IEEE754 double-precision special values. It 23 | # provides constants for Not-a-Number (NaN), Positive 24 | # Infinity (PosInf), and Negative Infinity (NegInf), as well 25 | # as functions to test for these values. 26 | # 27 | # More: http://www.python.org/dev/peps/pep-0754/ 28 | 29 | PosInf = 1e300000 30 | NegInf = -PosInf 31 | NaN = PosInf/PosInf 32 | 33 | def isPosInf(value): 34 | return PosInf == value 35 | 36 | def isNegInf(value): 37 | return NegInf == value 38 | 39 | def isInf(value): 40 | return PosInf == value or NegInf == value 41 | 42 | def isFinite(value): 43 | return PosInf > value > NegInf 44 | 45 | def isNaN(value): 46 | return isinstance(value, float) and value != value 47 | 48 | if __name__ == "__main__": 49 | def test_isNaN(): 50 | assert( not isNaN(PosInf) ) 51 | assert( not isNaN(NegInf) ) 52 | assert( isNaN(NaN ) ) 53 | assert( not isNaN( 1.0) ) 54 | assert( not isNaN( -1.0) ) 55 | 56 | def test_isInf(): 57 | assert( isInf(PosInf) ) 58 | assert( isInf(NegInf) ) 59 | assert( not isInf(NaN ) ) 60 | assert( not isInf( 1.0) ) 61 | assert( not isInf( -1.0) ) 62 | 63 | def test_isFinite(): 64 | assert( not isFinite(PosInf) ) 65 | assert( not isFinite(NegInf) ) 66 | assert( not isFinite(NaN ) ) 67 | assert( isFinite( 1.0) ) 68 | assert( isFinite( -1.0) ) 69 | 70 | def test_isPosInf(): 71 | assert( isPosInf(PosInf) ) 72 | assert( not isPosInf(NegInf) ) 73 | assert( not isPosInf(NaN ) ) 74 | assert( not isPosInf( 1.0) ) 75 | assert( not isPosInf( -1.0) ) 76 | 77 | def test_isNegInf(): 78 | assert( not isNegInf(PosInf) ) 79 | assert( isNegInf(NegInf) ) 80 | assert( not isNegInf(NaN ) ) 81 | assert( not isNegInf( 1.0) ) 82 | assert( not isNegInf( -1.0) ) 83 | 84 | # overall test 85 | def test(): 86 | test_isNaN() 87 | test_isInf() 88 | test_isFinite() 89 | test_isPosInf() 90 | test_isNegInf() 91 | 92 | test() -------------------------------------------------------------------------------- /python2/hprose/client.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/client.py # 13 | # # 14 | # hprose client for python 2.3+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import threading 22 | from cStringIO import StringIO 23 | from sys import modules 24 | from hprose.io import HproseTags, HproseWriter, HproseReader 25 | from hprose.common import HproseResultMode, HproseException 26 | 27 | class _Method(object): 28 | def __init__(self, invoke, name): 29 | self.__invoke = invoke 30 | self.__name = name 31 | def __getattr__(self, name): 32 | return _Method(self.__invoke, self.__name + '_' + name) 33 | def __call__(self, *args, **kargs): 34 | callback = kargs.get('callback', None) 35 | onerror = kargs.get('onerror', None) 36 | byref = kargs.get('byref', False) 37 | resultMode = kargs.get('resultMode', HproseResultMode.Normal) 38 | simple = kargs.get('simple', None) 39 | return self.__invoke(self.__name, list(args), callback, onerror, byref, resultMode, simple) 40 | 41 | class _Proxy(object): 42 | def __init__(self, invoke): 43 | self.__invoke = invoke 44 | def __getattr__(self, name): 45 | return _Method(self.__invoke, name) 46 | 47 | class _AsyncInvoke(object): 48 | def __init__(self, invoke, name, args, callback, onerror, byref, resultMode, simple): 49 | self.__invoke = invoke 50 | self.__name = name 51 | self.__args = args 52 | self.__callback = callback 53 | self.__onerror = onerror 54 | self.__byref = byref 55 | self.__resultMode = resultMode 56 | self.__simple = simple 57 | def __call__(self): 58 | try: 59 | result = self.__invoke(self.__name, self.__args, self.__byref, self.__resultMode, self.__simple) 60 | argcount = self.__callback.func_code.co_argcount 61 | if argcount == 0: 62 | self.__callback() 63 | elif argcount == 1: 64 | self.__callback(result) 65 | else: 66 | self.__callback(result, self.__args) 67 | except (KeyboardInterrupt, SystemExit): 68 | raise 69 | except Exception, e: 70 | if self.__onerror != None: 71 | self.__onerror(self.__name, e) 72 | 73 | class HproseClient(object): 74 | def __init__(self, uri = None): 75 | self.__filters = [] 76 | self.onError = None 77 | self.simple = False 78 | self._uri = uri 79 | self.useService(uri) 80 | 81 | def __getattr__(self, name): 82 | return _Method(self.invoke, name) 83 | 84 | def invoke(self, name, args = (), callback = None, onerror = None, byref = False, resultMode = HproseResultMode.Normal, simple = None): 85 | if simple == None: simple = self.simple 86 | if callback == None: 87 | return self.__invoke(name, args, byref, resultMode, simple) 88 | else: 89 | if isinstance(callback, (str, unicode)): 90 | callback = getattr(modules['__main__'], callback, None) 91 | if not callable(callback): 92 | raise HproseException, "callback must be callable" 93 | if onerror == None: 94 | onerror = self.onError 95 | if onerror != None: 96 | if isinstance(onerror, (str, unicode)): 97 | onerror = getattr(modules['__main__'], onerror, None) 98 | if not callable(onerror): 99 | raise HproseException, "onerror must be callable" 100 | threading.Thread(target = _AsyncInvoke(self.__invoke, name, args, 101 | callback, onerror, 102 | byref, resultMode, simple)).start() 103 | 104 | def useService(self, uri = None): 105 | if uri != None: self.setUri(uri) 106 | return _Proxy(self.invoke) 107 | 108 | def setUri(self, uri): 109 | self._uri = uri 110 | 111 | uri = property(fset = setUri) 112 | 113 | def getFilter(self): 114 | if (len(self.__filters) == 0): 115 | return None 116 | return self.__filters[0] 117 | 118 | def setFilter(self, _filter): 119 | self.__filters = [] 120 | if _filter != None: 121 | self.__filters.append(_filter) 122 | 123 | filter = property(fget = getFilter, fset = setFilter) 124 | 125 | def addFilter(self, _filter): 126 | self.__filters.append(_filter) 127 | 128 | def removeFilter(self, _filter): 129 | self.__filters.remove(_filter) 130 | 131 | def _sendAndReceive(self, data): 132 | raise NotImplementedError 133 | 134 | def __doOutput(self, name, args, byref, simple): 135 | stream = StringIO() 136 | writer = HproseWriter(stream, simple) 137 | stream.write(HproseTags.TagCall) 138 | writer.writeString(name) 139 | if (len(args) > 0) or byref: 140 | writer.reset() 141 | writer.writeList(args) 142 | if byref: writer.writeBoolean(True) 143 | stream.write(HproseTags.TagEnd) 144 | data = stream.getvalue() 145 | stream.close() 146 | for _filter in self.__filters: 147 | data = _filter.outputFilter(data, self) 148 | return data 149 | 150 | def __doInput(self, data, args, resultMode): 151 | for _filter in reversed(self.__filters): 152 | data = _filter.inputFilter(data, self) 153 | if data == None or len(data) == 0 or data[len(data) - 1] != HproseTags.TagEnd: 154 | raise HproseException, "Wrong Response: \r\n%s" % data 155 | if resultMode == HproseResultMode.RawWithEndTag: 156 | return data 157 | if resultMode == HproseResultMode.Raw: 158 | return data[:-1] 159 | stream = StringIO(data) 160 | reader = HproseReader(stream) 161 | result = None 162 | try: 163 | error = None 164 | while True: 165 | tag = stream.read(1) 166 | if tag == HproseTags.TagEnd: 167 | break 168 | elif tag == HproseTags.TagResult: 169 | if resultMode == HproseResultMode.Normal: 170 | reader.reset() 171 | result = reader.unserialize() 172 | else: 173 | s = reader.readRaw() 174 | result = s.getvalue() 175 | s.close() 176 | elif tag == HproseTags.TagArgument: 177 | reader.reset() 178 | a = reader.readList() 179 | if isinstance(args, list): 180 | for i in xrange(len(args)): 181 | args[i] = a[i] 182 | elif tag == HproseTags.TagError: 183 | reader.reset() 184 | error = reader.readString() 185 | else: 186 | raise HproseException, "Wrong Response: \r\n%s" % data 187 | if error != None: 188 | raise HproseException, error 189 | finally: 190 | stream.close() 191 | return result 192 | 193 | def __invoke(self, name, args, byref, resultMode, simple): 194 | data = self.__doOutput(name, args, byref, simple) 195 | data = self._sendAndReceive(data) 196 | return self.__doInput(data, args, resultMode) 197 | -------------------------------------------------------------------------------- /python3/hprose/client.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/client.py # 13 | # # 14 | # hprose client for python 3.0+ # 15 | # # 16 | # LastModified: Dec 2, 2016 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import threading 22 | from sys import modules 23 | from hprose.io import BytesIO, HproseTags, HproseWriter, HproseReader 24 | from hprose.common import HproseResultMode, HproseException 25 | 26 | class _Method(object): 27 | def __init__(self, invoke, name): 28 | self.__invoke = invoke 29 | self.__name = name 30 | def __getattr__(self, name): 31 | return _Method(self.__invoke, self.__name + '_' + name) 32 | def __call__(self, *args, **kargs): 33 | callback = kargs.get('callback', None) 34 | onerror = kargs.get('onerror', None) 35 | byref = kargs.get('byref', False) 36 | resultMode = kargs.get('resultMode', HproseResultMode.Normal) 37 | simple = kargs.get('simple', None) 38 | return self.__invoke(self.__name, list(args), callback, onerror, byref, resultMode, simple) 39 | 40 | class _Proxy(object): 41 | def __init__(self, invoke): 42 | self.__invoke = invoke 43 | def __getattr__(self, name): 44 | return _Method(self.__invoke, name) 45 | 46 | class _AsyncInvoke(object): 47 | def __init__(self, invoke, name, args, callback, onerror, byref, resultMode, simple): 48 | self.__invoke = invoke 49 | self.__name = name 50 | self.__args = args 51 | self.__callback = callback 52 | self.__onerror = onerror 53 | self.__byref = byref 54 | self.__resultMode = resultMode 55 | self.__simple = simple 56 | def __call__(self): 57 | try: 58 | result = self.__invoke(self.__name, self.__args, self.__byref, self.__resultMode, self.__simple) 59 | if hasattr(self.__callback, '__code__'): 60 | argcount = self.__callback.__code__.co_argcount 61 | if argcount == 0: 62 | self.__callback() 63 | elif argcount == 1: 64 | self.__callback(result) 65 | else: 66 | self.__callback(result, self.__args) 67 | else: 68 | self.__callback(result, self.__args) 69 | except (KeyboardInterrupt, SystemExit): 70 | raise 71 | except Exception as e: 72 | if self.__onerror != None: 73 | self.__onerror(self.__name, e) 74 | 75 | class HproseClient(object): 76 | def __init__(self, uri = None): 77 | self.__filters = [] 78 | self.onError = None 79 | self.simple = False 80 | self._uri = uri 81 | self.useService(uri) 82 | 83 | def __getattr__(self, name): 84 | return _Method(self.invoke, name) 85 | 86 | def invoke(self, name, args = (), callback = None, onerror = None, byref = False, resultMode = HproseResultMode.Normal, simple = None): 87 | if simple == None: simple = self.simple 88 | if callback == None: 89 | return self.__invoke(name, args, byref, resultMode, simple) 90 | else: 91 | if isinstance(callback, str): 92 | callback = getattr(modules['__main__'], callback, None) 93 | if not hasattr(callback, '__call__'): 94 | raise HproseException("callback must be callable") 95 | if onerror == None: 96 | onerror = self.onError 97 | if onerror != None: 98 | if isinstance(onerror, str): 99 | onerror = getattr(modules['__main__'], onerror, None) 100 | if not hasattr(onerror, '__call__'): 101 | raise HproseException("onerror must be callable") 102 | threading.Thread(target = _AsyncInvoke(self.__invoke, name, args, 103 | callback, onerror, 104 | byref, resultMode, simple)).start() 105 | 106 | def useService(self, uri = None): 107 | if uri != None: self.setUri(uri) 108 | return _Proxy(self.invoke) 109 | 110 | def setUri(self, uri): 111 | self._uri = uri 112 | 113 | uri = property(fset = setUri) 114 | 115 | def getFilter(self): 116 | if (len(self.__filters) == 0): 117 | return None 118 | return self.__filters[0] 119 | 120 | def setFilter(self, _filter): 121 | self.__filters = [] 122 | if _filter != None: 123 | self.__filters.append(_filter) 124 | 125 | filter = property(fget = getFilter, fset = setFilter) 126 | 127 | def addFilter(self, _filter): 128 | self.__filters.append(_filter) 129 | 130 | def removeFilter(self, _filter): 131 | self.__filters.remove(_filter) 132 | 133 | def _sendAndReceive(self, data): 134 | raise NotImplementedError 135 | 136 | def __doOutput(self, name, args, byref, simple): 137 | stream = BytesIO() 138 | writer = HproseWriter(stream, simple) 139 | stream.write(HproseTags.TagCall) 140 | writer.writeString(name) 141 | if (len(args) > 0) or byref: 142 | writer.reset() 143 | writer.writeList(args) 144 | if byref: writer.writeBoolean(True) 145 | stream.write(HproseTags.TagEnd) 146 | data = stream.getvalue() 147 | stream.close() 148 | for _filter in self.__filters: 149 | data = _filter.outputFilter(data, self) 150 | return data 151 | 152 | def __doInput(self, data, args, resultMode): 153 | for _filter in reversed(self.__filters): 154 | data = _filter.inputFilter(data, self) 155 | if data == None or len(data) == 0 or data[len(data) - 1:] != HproseTags.TagEnd: 156 | raise HproseException("Wrong Response: \r\n%s" % str(data, 'utf-8')) 157 | if resultMode == HproseResultMode.RawWithEndTag: 158 | return data 159 | if resultMode == HproseResultMode.Raw: 160 | return data[:-1] 161 | stream = BytesIO(data) 162 | reader = HproseReader(stream) 163 | result = None 164 | try: 165 | error = None 166 | while True: 167 | tag = stream.read(1) 168 | if tag == HproseTags.TagEnd: 169 | break 170 | elif tag == HproseTags.TagResult: 171 | if resultMode == HproseResultMode.Normal: 172 | reader.reset() 173 | result = reader.unserialize() 174 | else: 175 | s = reader.readRaw() 176 | result = s.getvalue() 177 | s.close() 178 | elif tag == HproseTags.TagArgument: 179 | reader.reset() 180 | a = reader.readList() 181 | if isinstance(args, list): 182 | for i in range(len(args)): 183 | args[i] = a[i] 184 | elif tag == HproseTags.TagError: 185 | reader.reset() 186 | error = reader.readString() 187 | else: 188 | raise HproseException("Wrong Response: \r\n%s" % str(data, 'utf-8')) 189 | if error != None: 190 | raise HproseException(error) 191 | finally: 192 | stream.close() 193 | return result 194 | 195 | def __invoke(self, name, args, byref, resultMode, simple): 196 | data = self.__doOutput(name, args, byref, simple) 197 | data = self._sendAndReceive(data) 198 | return self.__doInput(data, args, resultMode) 199 | -------------------------------------------------------------------------------- /python3/hprose/httpserver.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/httpserver.py # 13 | # # 14 | # hprose httpserver for python 3.0+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import re, datetime 22 | import urllib.parse 23 | from math import trunc 24 | from random import random 25 | from hprose.server import HproseService 26 | 27 | class HproseHttpService(HproseService): 28 | def __init__(self, sessionName = None): 29 | super(HproseHttpService, self).__init__() 30 | self.crossDomain = False 31 | self.p3p = False 32 | self.get = True 33 | self.onSendHeader = None 34 | self._origins = {} 35 | self._crossDomainXmlFile = None 36 | self._crossDomainXmlContent = None 37 | self._clientAccessPolicyXmlFile = None 38 | self._clientAccessPolicyXmlContent = None 39 | self._lastModified = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") 40 | self._etag = '"%x:%x"' % (trunc(random() * 2147483647), trunc(random() * 2147483647)) 41 | 42 | def __call__(self, environ, start_response = None): 43 | result = self.handle(environ) 44 | # WSGI 2 45 | if start_response == None: 46 | return result 47 | # WSGI 1 48 | start_response(result[0], result[1]) 49 | return result[2] 50 | 51 | def addAccessControlAllowOrigin(self, origin): 52 | self._origins[origin] = True 53 | 54 | def removeAccessControlAllowOrigin(self, origin): 55 | del self._origins[origin] 56 | 57 | def _crossDomainXmlHandler(self, environ): 58 | path = (environ['SCRIPT_NAME'] + environ['PATH_INFO']).lower() 59 | if (path == '/crossdomain.xml'): 60 | if ((environ.get('HTTP_IF_MODIFIED_SINCE', '') == self._lastModified) and 61 | (environ.get('HTTP_IF_NONE_MATCH', '') == self._etag)): 62 | return ['304 Not Modified', [], [b'']] 63 | else: 64 | header = [('Content-Type', 'text/xml'), 65 | ('Last-Modified', self._lastModified), 66 | ('Etag', self._etag)] 67 | return ['200 OK', header, [self._crossDomainXmlContent]] 68 | return False 69 | 70 | def _clientAccessPolicyXmlHandler(self, environ): 71 | path = (environ['SCRIPT_NAME'] + environ['PATH_INFO']).lower() 72 | if (path == '/clientaccesspolicy.xml'): 73 | if ((environ.get('HTTP_IF_MODIFIED_SINCE', '') == self._lastModified) and 74 | (environ.get('HTTP_IF_NONE_MATCH', '') == self._etag)): 75 | return ['304 Not Modified', [], [b'']] 76 | else: 77 | header = [('Content-Type', 'text/xml'), 78 | ('Last-Modified', self._lastModified), 79 | ('Etag', self._etag)] 80 | return ['200 OK', header, [self._clientAccessPolicyXmlContent]] 81 | return False 82 | 83 | def _header(self, environ): 84 | header = [('Content-Type', 'text/plain')] 85 | if self.p3p: 86 | header.append(('P3P', 'CP="CAO DSP COR CUR ADM DEV TAI PSA PSD ' + 87 | 'IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi ' + 88 | 'PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT ' + 89 | 'STA POL HEA PRE GOV"')) 90 | if self.crossDomain: 91 | origin = environ.get("HTTP_ORIGIN", "null") 92 | if origin != "null": 93 | if (len(self._origins) == 0) or self._origins[origin]: 94 | header.append(("Access-Control-Allow-Origin", origin)) 95 | header.append(("Access-Control-Allow-Credentials", "true")) 96 | else: 97 | header.append(("Access-Control-Allow-Origin", "*")) 98 | if self.onSendHeader != None: 99 | self.onSendHeader(environ, header) 100 | return header 101 | 102 | def handle(self, environ): 103 | if (self._clientAccessPolicyXmlContent != None): 104 | result = self._clientAccessPolicyXmlHandler(environ) 105 | if (result): return result 106 | if (self._crossDomainXmlContent != None): 107 | result = self._crossDomainXmlHandler(environ) 108 | if (result): return result 109 | header = self._header(environ) 110 | statuscode = '200 OK' 111 | body = b'' 112 | try: 113 | if environ['REQUEST_METHOD'] == 'GET' and self.get: 114 | body = self._doFunctionList(environ) 115 | elif environ['REQUEST_METHOD'] == 'POST': 116 | data = environ['wsgi.input'].read(int(environ.get("CONTENT_LENGTH", 0))) 117 | body = self._handle(data, environ) 118 | finally: 119 | return [statuscode, header, [body]] 120 | 121 | def _getCrossDomainXmlFile(self): 122 | return self._crossDomainXmlFile 123 | 124 | def _setCrossDomainXmlFile(self, value): 125 | self._crossDomainXmlFile = value 126 | f = open(value) 127 | try: 128 | self._crossDomainXmlContent = f.read() 129 | finally: 130 | f.close() 131 | 132 | crossDomainXmlFile = property(fget = _getCrossDomainXmlFile, fset = _setCrossDomainXmlFile) 133 | 134 | def _getCrossDomainXmlContent(self): 135 | return self._crossDomainXmlContent 136 | 137 | def _setCrossDomainXmlContent(self, value): 138 | self._crossDomainXmlFile = None 139 | self._crossDomainXmlContent = value 140 | 141 | crossDomainXmlContent = property(fget = _getCrossDomainXmlContent, fset = _setCrossDomainXmlContent) 142 | 143 | def _getClientAccessPolicyXmlFile(self): 144 | return self._clientAccessPolicyXmlFile 145 | 146 | def _setClientAccessPolicyXmlFile(self, value): 147 | self._clientAccessPolicyXmlFile = value 148 | f = open(value) 149 | try: 150 | self._clientAccessPolicyXmlContent = f.read() 151 | finally: 152 | f.close() 153 | 154 | clientAccessPolicyXmlFile = property(fget = _getClientAccessPolicyXmlFile, fset = _setClientAccessPolicyXmlFile) 155 | 156 | def _getClientAccessPolicyXmlContent(self): 157 | return self._clientAccessPolicyXmlContent 158 | 159 | def _setClientAccessPolicyXmlContent(self, value): 160 | self._clientAccessPolicyXmlFile = None 161 | self._clientAccessPolicyXmlContent = value 162 | 163 | clientAccessPolicyXmlContent = property(fget = _getClientAccessPolicyXmlContent, fset = _setClientAccessPolicyXmlContent) 164 | 165 | ################################################################################ 166 | # UrlMapMiddleware # 167 | ################################################################################ 168 | 169 | class UrlMapMiddleware: 170 | def __init__(self, url_mapping): 171 | self.__init_url_mappings(url_mapping) 172 | 173 | def __init_url_mappings(self, url_mapping): 174 | self.__url_mapping = [] 175 | for regexp, app in url_mapping: 176 | if not regexp.startswith('^'): 177 | regexp = '^' + regexp 178 | if not regexp.endswith('$'): 179 | regexp += '$' 180 | compiled = re.compile(regexp) 181 | self.__url_mapping.append((compiled, app)) 182 | 183 | def __call__(self, environ, start_response = None): 184 | script_name = environ['SCRIPT_NAME'] 185 | path_info = environ['PATH_INFO'] 186 | path = urllib.parse.quote(script_name) + urllib.parse.quote(path_info) 187 | for regexp, app in self.__url_mapping: 188 | if regexp.match(path): return app(environ, start_response) 189 | if start_response: 190 | start_response('404 Not Found', [('Content-Type', 'text/plain')]) 191 | return [b'404 Not Found'] 192 | return ('404 Not Found', [('Content-Type', 'text/plain')], [b'404 Not Found']) 193 | 194 | ################################################################################ 195 | # HproseHttpServer # 196 | ################################################################################ 197 | 198 | class HproseHttpServer(HproseHttpService): 199 | def __init__(self, host = '', port = 80, app = None): 200 | super(HproseHttpServer, self).__init__() 201 | self.host = host 202 | self.port = port 203 | if app == None: 204 | self.app = self 205 | else: 206 | self.app = app 207 | 208 | def start(self): 209 | print("Serving on port %s:%s..." % (self.host, self.port)) 210 | from wsgiref.simple_server import make_server 211 | httpd = make_server(self.host, self.port, self.app) 212 | try: 213 | httpd.serve_forever() 214 | except KeyboardInterrupt: 215 | exit() 216 | -------------------------------------------------------------------------------- /python2/hprose/httpserver.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/httpserver.py # 13 | # # 14 | # hprose httpserver for python 2.3+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import re, urllib, datetime 22 | from math import trunc 23 | from random import random 24 | from hprose.server import HproseService 25 | 26 | class HproseHttpService(HproseService): 27 | def __init__(self): 28 | super(HproseHttpService, self).__init__() 29 | self.crossDomain = False 30 | self.p3p = False 31 | self.get = True 32 | self._origins = {} 33 | self._crossDomainXmlFile = None 34 | self._crossDomainXmlContent = None 35 | self._clientAccessPolicyXmlFile = None 36 | self._clientAccessPolicyXmlContent = None 37 | self._lastModified = datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") 38 | self._etag = '"%x:%x"' % (trunc(random() * 2147483647), trunc(random() * 2147483647)) 39 | self.onSendHeader = None 40 | def __call__(self, environ, start_response = None): 41 | result = self.handle(environ) 42 | # WSGI 2 43 | if start_response == None: 44 | return result 45 | # WSGI 1 46 | start_response(result[0], result[1]) 47 | return result[2] 48 | 49 | def addAccessControlAllowOrigin(self, origin): 50 | self._origins[origin] = True 51 | 52 | def removeAccessControlAllowOrigin(self, origin): 53 | del self._origins[origin] 54 | 55 | def _crossDomainXmlHandler(self, environ): 56 | path = (environ['SCRIPT_NAME'] + environ['PATH_INFO']).lower() 57 | if (path == '/crossdomain.xml'): 58 | if ((environ.get('HTTP_IF_MODIFIED_SINCE', '') == self._lastModified) and 59 | (environ.get('HTTP_IF_NONE_MATCH', '') == self._etag)): 60 | return ['304 Not Modified', [], ['']] 61 | else: 62 | header = [('Content-Type', 'text/xml'), 63 | ('Last-Modified', self._lastModified), 64 | ('Etag', self._etag)] 65 | return ['200 OK', header, [self._crossDomainXmlContent]] 66 | return False 67 | 68 | def _clientAccessPolicyXmlHandler(self, environ): 69 | path = (environ['SCRIPT_NAME'] + environ['PATH_INFO']).lower() 70 | if (path == '/clientaccesspolicy.xml'): 71 | if ((environ.get('HTTP_IF_MODIFIED_SINCE', '') == self._lastModified) and 72 | (environ.get('HTTP_IF_NONE_MATCH', '') == self._etag)): 73 | return ['304 Not Modified', [], ['']] 74 | else: 75 | header = [('Content-Type', 'text/xml'), 76 | ('Last-Modified', self._lastModified), 77 | ('Etag', self._etag)] 78 | return ['200 OK', header, [self._clientAccessPolicyXmlContent]] 79 | return False 80 | 81 | def _header(self, environ): 82 | header = [('Content-Type', 'text/plain')] 83 | if self.p3p: 84 | header.append(('P3P', 'CP="CAO DSP COR CUR ADM DEV TAI PSA PSD ' + 85 | 'IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi ' + 86 | 'PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT ' + 87 | 'STA POL HEA PRE GOV"')) 88 | if self.crossDomain: 89 | origin = environ.get("HTTP_ORIGIN", "null") 90 | if origin != "null": 91 | if (len(self._origins) == 0) or self._origins[origin]: 92 | header.append(("Access-Control-Allow-Origin", origin)) 93 | header.append(("Access-Control-Allow-Credentials", "true")) 94 | else: 95 | header.append(("Access-Control-Allow-Origin", "*")) 96 | if self.onSendHeader != None: 97 | self.onSendHeader(environ, header) 98 | return header 99 | 100 | def handle(self, environ): 101 | if (self._clientAccessPolicyXmlContent != None): 102 | result = self._clientAccessPolicyXmlHandler(environ) 103 | if result: return result 104 | if (self._crossDomainXmlContent != None): 105 | result = self._crossDomainXmlHandler(environ) 106 | if result: return result 107 | header = self._header(environ) 108 | statuscode = '200 OK' 109 | body = '' 110 | try: 111 | if ((environ['REQUEST_METHOD'] == 'GET') and self.get): 112 | body = self._doFunctionList(environ) 113 | elif (environ['REQUEST_METHOD'] == 'POST'): 114 | data = environ['wsgi.input'].read(int(environ.get("CONTENT_LENGTH", 0))) 115 | body = self._handle(data, environ) 116 | else: 117 | statuscode = '403 Forbidden' 118 | finally: 119 | return [statuscode, header, [body]] 120 | 121 | def _getCrossDomainXmlFile(self): 122 | return self._crossDomainXmlFile 123 | 124 | def _setCrossDomainXmlFile(self, value): 125 | self._crossDomainXmlFile = value 126 | f = open(value) 127 | try: 128 | self._crossDomainXmlContent = f.read() 129 | finally: 130 | f.close() 131 | 132 | crossDomainXmlFile = property(fget = _getCrossDomainXmlFile, fset = _setCrossDomainXmlFile) 133 | 134 | def _getCrossDomainXmlContent(self): 135 | return self._crossDomainXmlContent 136 | 137 | def _setCrossDomainXmlContent(self, value): 138 | self._crossDomainXmlFile = None 139 | self._crossDomainXmlContent = value 140 | 141 | crossDomainXmlContent = property(fget = _getCrossDomainXmlContent, fset = _setCrossDomainXmlContent) 142 | 143 | def _getClientAccessPolicyXmlFile(self): 144 | return self._clientAccessPolicyXmlFile 145 | 146 | def _setClientAccessPolicyXmlFile(self, value): 147 | self._clientAccessPolicyXmlFile = value 148 | f = open(value) 149 | try: 150 | self._clientAccessPolicyXmlContent = f.read() 151 | finally: 152 | f.close() 153 | 154 | clientAccessPolicyXmlFile = property(fget = _getClientAccessPolicyXmlFile, fset = _setClientAccessPolicyXmlFile) 155 | 156 | def _getClientAccessPolicyXmlContent(self): 157 | return self._clientAccessPolicyXmlContent 158 | 159 | def _setClientAccessPolicyXmlContent(self, value): 160 | self._clientAccessPolicyXmlFile = None 161 | self._clientAccessPolicyXmlContent = value 162 | 163 | clientAccessPolicyXmlContent = property(fget = _getClientAccessPolicyXmlContent, fset = _setClientAccessPolicyXmlContent) 164 | 165 | ################################################################################ 166 | # UrlMapMiddleware # 167 | ################################################################################ 168 | 169 | class UrlMapMiddleware: 170 | def __init__(self, url_mapping): 171 | self.__init_url_mappings(url_mapping) 172 | 173 | def __init_url_mappings(self, url_mapping): 174 | self.__url_mapping = [] 175 | for regexp, app in url_mapping: 176 | if not regexp.startswith('^'): 177 | regexp = '^' + regexp 178 | if not regexp.endswith('$'): 179 | regexp += '$' 180 | compiled = re.compile(regexp) 181 | self.__url_mapping.append((compiled, app)) 182 | 183 | def __call__(self, environ, start_response = None): 184 | script_name = environ['SCRIPT_NAME'] 185 | path_info = environ['PATH_INFO'] 186 | path = urllib.quote(script_name) + urllib.quote(path_info) 187 | for regexp, app in self.__url_mapping: 188 | if regexp.match(path): return app(environ, start_response) 189 | if start_response: 190 | start_response('404 Not Found', [('Content-Type', "text/plain")]) 191 | return ['404 Not Found'] 192 | return ('404 Not Found', [('Content-Type', "text/plain")], ['404 Not Found']) 193 | 194 | ################################################################################ 195 | # HproseHttpServer # 196 | ################################################################################ 197 | 198 | class HproseHttpServer(HproseHttpService): 199 | def __init__(self, host = '', port = 80, app = None): 200 | super(HproseHttpServer, self).__init__() 201 | self.host = host 202 | self.port = port 203 | if app == None: 204 | self.app = self 205 | else: 206 | self.app = app 207 | 208 | def start(self): 209 | print "Serving on port %s:%s..." % (self.host, self.port) 210 | from wsgiref.simple_server import make_server 211 | httpd = make_server(self.host, self.port, self.app) 212 | try: 213 | httpd.serve_forever() 214 | except KeyboardInterrupt: 215 | exit() 216 | -------------------------------------------------------------------------------- /python3/hprose/httpclient.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/httpclient.py # 13 | # # 14 | # hprose httpclient for python 3.0+ # 15 | # # 16 | # LastModified: Dec 25, 2018 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import http.client, re, threading 22 | import urllib.parse 23 | from calendar import timegm 24 | from hprose.common import HproseException 25 | import time 26 | from hprose.client import HproseClient 27 | 28 | # _http2time from cookielib.py in python 2.5 29 | EPOCH_YEAR = 1970 30 | 31 | MONTHS_LOWER = ["jan", "feb", "mar", "apr", "may", "jun", 32 | "jul", "aug", "sep", "oct", "nov", "dec"] 33 | 34 | def _timegm(tt): 35 | year, month, mday, hour, minute, sec = tt[:6] 36 | if ((year >= EPOCH_YEAR) and (1 <= month <= 12) and (1 <= mday <= 31) and 37 | (0 <= hour <= 24) and (0 <= minute <= 59) and (0 <= sec <= 61)): 38 | return timegm(tt) 39 | else: 40 | return None 41 | 42 | UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None} 43 | 44 | TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$") 45 | 46 | def offset_from_tz_string(tz): 47 | offset = None 48 | if tz in UTC_ZONES: 49 | offset = 0 50 | else: 51 | m = TIMEZONE_RE.search(tz) 52 | if m: 53 | offset = 3600 * int(m.group(2)) 54 | if m.group(3): 55 | offset = offset + 60 * int(m.group(3)) 56 | if m.group(1) == '-': 57 | offset = -offset 58 | return offset 59 | 60 | def _str2time(day, mon, yr, hr, minute, sec, tz): 61 | # translate month name to number 62 | # month numbers start with 1 (January) 63 | try: 64 | mon = MONTHS_LOWER.index(mon.lower())+1 65 | except ValueError: 66 | # maybe it's already a number 67 | try: 68 | imon = int(mon) 69 | except ValueError: 70 | return None 71 | if 1 <= imon <= 12: 72 | mon = imon 73 | else: 74 | return None 75 | 76 | # make sure clock elements are defined 77 | if hr is None: hr = 0 78 | if minute is None: minute = 0 79 | if sec is None: sec = 0 80 | 81 | yr = int(yr) 82 | day = int(day) 83 | hr = int(hr) 84 | minute = int(minute) 85 | sec = int(sec) 86 | 87 | if yr < 1000: 88 | # find "obvious" year 89 | cur_yr = time.localtime(time.time())[0] 90 | m = cur_yr % 100 91 | tmp = yr 92 | yr = yr + cur_yr - m 93 | m = m - tmp 94 | if abs(m) > 50: 95 | if m > 0: yr = yr + 100 96 | else: yr = yr - 100 97 | 98 | # convert UTC time tuple to seconds since epoch (not timezone-adjusted) 99 | t = _timegm((yr, mon, day, hr, min, sec, tz)) 100 | 101 | if t is not None: 102 | # adjust time using timezone string, to get absolute time since epoch 103 | if tz is None: 104 | tz = "UTC" 105 | tz = tz.upper() 106 | offset = offset_from_tz_string(tz) 107 | if offset is None: 108 | return None 109 | t = t - offset 110 | 111 | return t 112 | 113 | STRICT_DATE_RE = re.compile( 114 | r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$") 115 | WEEKDAY_RE = re.compile( 116 | r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I) 117 | LOOSE_HTTP_DATE_RE = re.compile( 118 | r"""^ 119 | (\d\d?) # day 120 | (?:\s+|[-\/]) 121 | (\w+) # month 122 | (?:\s+|[-\/]) 123 | (\d+) # year 124 | (?: 125 | (?:\s+|:) # separator before clock 126 | (\d\d?):(\d\d) # hour:min 127 | (?::(\d\d))? # optional seconds 128 | )? # optional clock 129 | \s* 130 | ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone 131 | \s* 132 | (?:\(\w+\))? # ASCII representation of timezone in parens. 133 | \s*$""", re.X) 134 | def _http2time(text): 135 | """Returns time in seconds since epoch of time represented by a string. 136 | 137 | Return value is an integer. 138 | 139 | None is returned if the format of str is unrecognized, the time is outside 140 | the representable range, or the timezone string is not recognized. If the 141 | string contains no timezone, UTC is assumed. 142 | 143 | The timezone in the string may be numerical (like "-0800" or "+0100") or a 144 | string timezone (like "UTC", "GMT", "BST" or "EST"). Currently, only the 145 | timezone strings equivalent to UTC (zero offset) are known to the function. 146 | 147 | The function loosely parses the following formats: 148 | 149 | Wed, 09 Feb 1994 22:23:32 GMT -- HTTP format 150 | Tuesday, 08-Feb-94 14:15:29 GMT -- old rfc850 HTTP format 151 | Tuesday, 08-Feb-1994 14:15:29 GMT -- broken rfc850 HTTP format 152 | 09 Feb 1994 22:23:32 GMT -- HTTP format (no weekday) 153 | 08-Feb-94 14:15:29 GMT -- rfc850 format (no weekday) 154 | 08-Feb-1994 14:15:29 GMT -- broken rfc850 format (no weekday) 155 | 156 | The parser ignores leading and trailing whitespace. The time may be 157 | absent. 158 | 159 | If the year is given with only 2 digits, the function will select the 160 | century that makes the year closest to the current date. 161 | 162 | """ 163 | # fast exit for strictly conforming string 164 | m = STRICT_DATE_RE.search(text) 165 | if m: 166 | g = m.groups() 167 | mon = MONTHS_LOWER.index(g[1].lower()) + 1 168 | tt = (int(g[2]), mon, int(g[0]), 169 | int(g[3]), int(g[4]), float(g[5])) 170 | return _timegm(tt) 171 | 172 | # No, we need some messy parsing... 173 | 174 | # clean up 175 | text = text.lstrip() 176 | text = WEEKDAY_RE.sub("", text, 1) # Useless weekday 177 | 178 | # tz is time zone specifier string 179 | day, mon, yr, hr, minute, sec, tz = [None]*7 180 | 181 | # loose regexp parse 182 | m = LOOSE_HTTP_DATE_RE.search(text) 183 | if m is not None: 184 | day, mon, yr, hr, minute, sec, tz = m.groups() 185 | else: 186 | return None # bad format 187 | 188 | return _str2time(day, mon, yr, hr, minute, sec, tz) 189 | 190 | _cookieManager = {} 191 | _cookieManagerLock = threading.RLock() 192 | 193 | def _setCookie(cookieList, host): 194 | _cookieManagerLock.acquire() 195 | try: 196 | for cookies in cookieList: 197 | if cookies == '': continue 198 | cookies = cookies.strip().split(';') 199 | cookie = {} 200 | value = cookies[0].strip().split('=', 1) 201 | cookie['name'] = value[0] 202 | if len(value) == 2: 203 | cookie['value'] = value[1] 204 | else: 205 | cookie['value'] = '' 206 | for i in range(1, len(cookies)): 207 | value = cookies[i].strip().split('=', 1) 208 | if len(value) == 2: 209 | cookie[value[0].upper()] = value[1] 210 | else: 211 | cookie[value[0].upper()] = '' 212 | # Tomcat can return SetCookie2 with path wrapped in " 213 | if 'PATH' in cookie: 214 | if cookie['PATH'][0] == '"': 215 | cookie['PATH'] = cookie['PATH'][1:] 216 | if cookie['PATH'][-1] == '"': 217 | cookie['PATH'] = cookie['PATH'][:-1] 218 | else: 219 | cookie['PATH'] = '/' 220 | if 'EXPIRES' in cookie: 221 | cookie['EXPIRES'] = _http2time(cookie['EXPIRES']) 222 | if 'DOMAIN' in cookie: 223 | cookie['DOMAIN'] = cookie['DOMAIN'].lower() 224 | else: 225 | cookie['DOMAIN'] = host 226 | cookie['SECURE'] = 'SECURE' in cookie 227 | if (cookie['DOMAIN'] not in _cookieManager): 228 | _cookieManager[cookie['DOMAIN']] = {} 229 | _cookieManager[cookie['DOMAIN']][cookie['name']] = cookie 230 | finally: 231 | _cookieManagerLock.release() 232 | 233 | def _getCookie(host, path, secure): 234 | cookies = [] 235 | _cookieManagerLock.acquire() 236 | try: 237 | for domain in _cookieManager: 238 | cookieList = _cookieManager[domain] 239 | if host.endswith(domain): 240 | names = [] 241 | for name in cookieList: 242 | cookie = cookieList[name] 243 | if 'EXPIRES' in cookie and time.time() > cookie['EXPIRES']: 244 | names.append(name) 245 | elif path.startswith(cookie['PATH']): 246 | if (((secure and cookie['SECURE']) or 247 | not cookie['SECURE']) and cookie['value'] != ''): 248 | cookies.append(cookie['name'] + '=' + cookie['value']) 249 | for name in names: 250 | del _cookieManager[domain][name] 251 | finally: 252 | _cookieManagerLock.release() 253 | if len(cookies) > 0: 254 | return '; '.join(cookies) 255 | return '' 256 | 257 | class HproseHttpClient(HproseClient): 258 | def __init__(self, uri = None): 259 | self.__header = {} 260 | self.__proxy = None 261 | self.timeout = 30 262 | self.keepAlive = True 263 | self.keepAliveTimeout = 300 264 | self.__scheme = None 265 | self.__port = None 266 | self.__host = None 267 | self.__ip = None 268 | self.__path = None 269 | self.__query = None 270 | self.__fragment = None 271 | self.__conn = None 272 | super(HproseHttpClient, self).__init__(uri) 273 | 274 | def setUri(self, uri): 275 | super(HproseHttpClient, self).setUri(uri) 276 | uri = urllib.parse.urlsplit(uri, 'http') 277 | self.__scheme = uri[0] 278 | if self.__scheme == 'https': 279 | self.__port = 443 280 | else: 281 | self.__port = 80 282 | netloc = uri[1] 283 | if "@" in netloc: 284 | netloc = netloc.split("@", 1)[1] 285 | if ":" in netloc: 286 | netloc = netloc.split(":", 1) 287 | self.__port = int(netloc[1]) 288 | netloc = netloc[0] 289 | self.__host = netloc.lower() 290 | if self.__host == 'localhost': 291 | self.__ip = '127.0.0.1' 292 | else: 293 | self.__ip = self.__host 294 | self.__path = uri[2] 295 | self.__query = uri[-2] 296 | self.__fragment = uri[-1] 297 | 298 | def setProxy(self, host, port = None): 299 | if host == None: 300 | self.__proxy = None 301 | else: 302 | proxy = urllib.parse.urlsplit(host) 303 | scheme = proxy[0] 304 | if port == None: 305 | if self.__scheme == 'https': 306 | port = 443 307 | else: 308 | port = 80 309 | netloc = proxy[1] 310 | if "@" in netloc: 311 | netloc = netloc.split("@", 1)[1] 312 | if ":" in netloc: 313 | netloc = netloc.split(":", 1) 314 | port = int(netloc[1]) 315 | netloc = netloc[0] 316 | host = netloc.lower() 317 | if host == 'localhost': 318 | ip = '127.0.0.1' 319 | else: 320 | ip = host 321 | self.__proxy = {'scheme': scheme, 'host': host, 'ip':ip, 'port': port} 322 | 323 | proxy = property(fset = setProxy) 324 | 325 | def setHeader(self, name, value): 326 | lname = name.lower() 327 | if (lname != 'content-type' and 328 | lname != 'content-length' and 329 | lname != 'host'): 330 | if value: 331 | self.__header[name] = value 332 | else: 333 | del self.__header[name] 334 | 335 | def __getconnect(self): 336 | if self.__proxy == None: 337 | if self.__scheme == 'https': 338 | httpclient = http.client.HTTPSConnection(self.__ip, self.__port, timeout = self.timeout) 339 | else: 340 | httpclient = http.client.HTTPConnection(self.__ip, self.__port, timeout = self.timeout) 341 | else: 342 | if self.__proxy['scheme'] == 'https': 343 | httpclient = http.client.HTTPSConnection(self.__proxy['ip'], self.__proxy['port'], timeout = self.timeout) 344 | else: 345 | httpclient = http.client.HTTPConnection(self.__proxy['ip'], self.__proxy['port'], timeout = self.timeout) 346 | return httpclient 347 | 348 | def __getconn(self): 349 | if not self.keepAlive: 350 | return self.__getconnect() 351 | if self.__conn == None: 352 | self.__conn = self.__getconnect() 353 | return self.__conn 354 | 355 | def _sendAndReceive(self, data): 356 | header = {'Content-Type': 'application/hprose'} 357 | header['Host'] = self.__host 358 | if (self.__port != 80): 359 | header['Host'] += ':' + str(self.__port) 360 | cookie = _getCookie(self.__host, self.__path, self.__scheme == 'https') 361 | if cookie != '': 362 | header['Cookie'] = cookie 363 | if self.keepAlive: 364 | header['Connection'] = 'keep-alive' 365 | header['Keep-Alive'] = str(self.keepAliveTimeout) 366 | else: 367 | header['Connection'] = 'close' 368 | for name in self.__header: header[name] = self.__header[name] 369 | httpclient = self.__getconn() 370 | if self.__proxy == None: 371 | path = urllib.parse.urlunsplit(('', '', self.__path, self.__query, self.__fragment)) 372 | else: 373 | path = self._uri 374 | httpclient.request('POST', path, data, header) 375 | resp = httpclient.getresponse() 376 | if resp.status == 200: 377 | cookieList = resp.getheader('set-cookie', '').split(',') 378 | cookieList.extend(resp.getheader('set-cookie2', '').split(',')) 379 | _setCookie(cookieList, self.__host) 380 | data = resp.read() 381 | if not self.keepAlive: 382 | httpclient.close() 383 | return data 384 | else: 385 | if not self.keepAlive: 386 | httpclient.close() 387 | raise HproseException('%d:%s' % (resp.status, resp.reason)) 388 | -------------------------------------------------------------------------------- /python2/hprose/httpclient.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/httpclient.py # 13 | # # 14 | # hprose httpclient for python 2.3+ # 15 | # # 16 | # LastModified: Dec 25, 2018 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import httplib, re, threading, urlparse 22 | from calendar import timegm 23 | from hprose.common import HproseException 24 | import time 25 | from hprose.client import HproseClient 26 | 27 | # _http2time from cookielib.py in python 2.5 28 | EPOCH_YEAR = 1970 29 | 30 | MONTHS_LOWER = ["jan", "feb", "mar", "apr", "may", "jun", 31 | "jul", "aug", "sep", "oct", "nov", "dec"] 32 | 33 | def _timegm(tt): 34 | year, month, mday, hour, minute, sec = tt[:6] 35 | if ((year >= EPOCH_YEAR) and (1 <= month <= 12) and (1 <= mday <= 31) and 36 | (0 <= hour <= 24) and (0 <= minute <= 59) and (0 <= sec <= 61)): 37 | return timegm(tt) 38 | else: 39 | return None 40 | 41 | UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None} 42 | 43 | TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$") 44 | 45 | def offset_from_tz_string(tz): 46 | offset = None 47 | if tz in UTC_ZONES: 48 | offset = 0 49 | else: 50 | m = TIMEZONE_RE.search(tz) 51 | if m: 52 | offset = 3600 * int(m.group(2)) 53 | if m.group(3): 54 | offset = offset + 60 * int(m.group(3)) 55 | if m.group(1) == '-': 56 | offset = -offset 57 | return offset 58 | 59 | def _str2time(day, mon, yr, hr, minute, sec, tz): 60 | # translate month name to number 61 | # month numbers start with 1 (January) 62 | try: 63 | mon = MONTHS_LOWER.index(mon.lower())+1 64 | except ValueError: 65 | # maybe it's already a number 66 | try: 67 | imon = int(mon) 68 | except ValueError: 69 | return None 70 | if 1 <= imon <= 12: 71 | mon = imon 72 | else: 73 | return None 74 | 75 | # make sure clock elements are defined 76 | if hr is None: hr = 0 77 | if minute is None: minute = 0 78 | if sec is None: sec = 0 79 | 80 | yr = int(yr) 81 | day = int(day) 82 | hr = int(hr) 83 | minute = int(minute) 84 | sec = int(sec) 85 | 86 | if yr < 1000: 87 | # find "obvious" year 88 | cur_yr = time.localtime(time.time())[0] 89 | m = cur_yr % 100 90 | tmp = yr 91 | yr = yr + cur_yr - m 92 | m = m - tmp 93 | if abs(m) > 50: 94 | if m > 0: yr = yr + 100 95 | else: yr = yr - 100 96 | 97 | # convert UTC time tuple to seconds since epoch (not timezone-adjusted) 98 | t = _timegm((yr, mon, day, hr, min, sec, tz)) 99 | 100 | if t is not None: 101 | # adjust time using timezone string, to get absolute time since epoch 102 | if tz is None: 103 | tz = "UTC" 104 | tz = tz.upper() 105 | offset = offset_from_tz_string(tz) 106 | if offset is None: 107 | return None 108 | t = t - offset 109 | 110 | return t 111 | 112 | STRICT_DATE_RE = re.compile( 113 | r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$") 114 | WEEKDAY_RE = re.compile( 115 | r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I) 116 | LOOSE_HTTP_DATE_RE = re.compile( 117 | r"""^ 118 | (\d\d?) # day 119 | (?:\s+|[-\/]) 120 | (\w+) # month 121 | (?:\s+|[-\/]) 122 | (\d+) # year 123 | (?: 124 | (?:\s+|:) # separator before clock 125 | (\d\d?):(\d\d) # hour:min 126 | (?::(\d\d))? # optional seconds 127 | )? # optional clock 128 | \s* 129 | ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone 130 | \s* 131 | (?:\(\w+\))? # ASCII representation of timezone in parens. 132 | \s*$""", re.X) 133 | def _http2time(text): 134 | """Returns time in seconds since epoch of time represented by a string. 135 | 136 | Return value is an integer. 137 | 138 | None is returned if the format of str is unrecognized, the time is outside 139 | the representable range, or the timezone string is not recognized. If the 140 | string contains no timezone, UTC is assumed. 141 | 142 | The timezone in the string may be numerical (like "-0800" or "+0100") or a 143 | string timezone (like "UTC", "GMT", "BST" or "EST"). Currently, only the 144 | timezone strings equivalent to UTC (zero offset) are known to the function. 145 | 146 | The function loosely parses the following formats: 147 | 148 | Wed, 09 Feb 1994 22:23:32 GMT -- HTTP format 149 | Tuesday, 08-Feb-94 14:15:29 GMT -- old rfc850 HTTP format 150 | Tuesday, 08-Feb-1994 14:15:29 GMT -- broken rfc850 HTTP format 151 | 09 Feb 1994 22:23:32 GMT -- HTTP format (no weekday) 152 | 08-Feb-94 14:15:29 GMT -- rfc850 format (no weekday) 153 | 08-Feb-1994 14:15:29 GMT -- broken rfc850 format (no weekday) 154 | 155 | The parser ignores leading and trailing whitespace. The time may be 156 | absent. 157 | 158 | If the year is given with only 2 digits, the function will select the 159 | century that makes the year closest to the current date. 160 | 161 | """ 162 | # fast exit for strictly conforming string 163 | m = STRICT_DATE_RE.search(text) 164 | if m: 165 | g = m.groups() 166 | mon = MONTHS_LOWER.index(g[1].lower()) + 1 167 | tt = (int(g[2]), mon, int(g[0]), 168 | int(g[3]), int(g[4]), float(g[5])) 169 | return _timegm(tt) 170 | 171 | # No, we need some messy parsing... 172 | 173 | # clean up 174 | text = text.lstrip() 175 | text = WEEKDAY_RE.sub("", text, 1) # Useless weekday 176 | 177 | # tz is time zone specifier string 178 | day, mon, yr, hr, minute, sec, tz = [None]*7 179 | 180 | # loose regexp parse 181 | m = LOOSE_HTTP_DATE_RE.search(text) 182 | if m is not None: 183 | day, mon, yr, hr, minute, sec, tz = m.groups() 184 | else: 185 | return None # bad format 186 | 187 | return _str2time(day, mon, yr, hr, minute, sec, tz) 188 | 189 | _cookieManager = {} 190 | _cookieManagerLock = threading.RLock() 191 | 192 | def _setCookie(cookieList, host): 193 | _cookieManagerLock.acquire() 194 | try: 195 | for cookies in cookieList: 196 | if cookies == '': continue 197 | cookies = cookies.strip().split(';') 198 | cookie = {} 199 | value = cookies[0].strip().split('=', 1) 200 | cookie['name'] = value[0] 201 | if len(value) == 2: 202 | cookie['value'] = value[1] 203 | else: 204 | cookie['value'] = '' 205 | for i in xrange(1, len(cookies)): 206 | value = cookies[i].strip().split('=', 1) 207 | if len(value) == 2: 208 | cookie[value[0].upper()] = value[1] 209 | else: 210 | cookie[value[0].upper()] = '' 211 | # Tomcat can return SetCookie2 with path wrapped in " 212 | if 'PATH' in cookie: 213 | if cookie['PATH'][0] == '"': 214 | cookie['PATH'] = cookie['PATH'][1:] 215 | if cookie['PATH'][-1] == '"': 216 | cookie['PATH'] = cookie['PATH'][:-1] 217 | else: 218 | cookie['PATH'] = '/' 219 | if 'EXPIRES' in cookie: 220 | cookie['EXPIRES'] = _http2time(cookie['EXPIRES']) 221 | if 'DOMAIN' in cookie: 222 | cookie['DOMAIN'] = cookie['DOMAIN'].lower() 223 | else: 224 | cookie['DOMAIN'] = host 225 | cookie['SECURE'] = 'SECURE' in cookie 226 | if (cookie['DOMAIN'] not in _cookieManager): 227 | _cookieManager[cookie['DOMAIN']] = {} 228 | _cookieManager[cookie['DOMAIN']][cookie['name']] = cookie 229 | finally: 230 | _cookieManagerLock.release() 231 | 232 | def _getCookie(host, path, secure): 233 | cookies = [] 234 | _cookieManagerLock.acquire() 235 | try: 236 | for domain in _cookieManager: 237 | cookieList = _cookieManager[domain] 238 | if host.endswith(domain): 239 | names = [] 240 | for name in cookieList: 241 | cookie = cookieList[name] 242 | if 'EXPIRES' in cookie and time.time() > cookie['EXPIRES']: 243 | names.append(name) 244 | elif path.startswith(cookie['PATH']): 245 | if (((secure and cookie['SECURE']) or 246 | not cookie['SECURE']) and cookie['value'] != ''): 247 | cookies.append(cookie['name'] + '=' + cookie['value']) 248 | for name in names: 249 | del _cookieManager[domain][name] 250 | finally: 251 | _cookieManagerLock.release() 252 | if len(cookies) > 0: 253 | return '; '.join(cookies) 254 | return '' 255 | 256 | class HproseHttpClient(HproseClient): 257 | def __init__(self, uri = None): 258 | self.__header = {} 259 | self.__proxy = None 260 | self.timeout = 30 261 | self.keepAlive = True 262 | self.keepAliveTimeout = 300 263 | self.__scheme = None 264 | self.__port = None 265 | self.__host = None 266 | self.__ip = None 267 | self.__path = None 268 | self.__query = None 269 | self.__fragment = None 270 | self.__conn = None 271 | super(HproseHttpClient, self).__init__(uri) 272 | 273 | def setUri(self, uri): 274 | super(HproseHttpClient, self).setUri(uri) 275 | uri = urlparse.urlsplit(uri, 'http') 276 | self.__scheme = uri[0] 277 | if self.__scheme == 'https': 278 | self.__port = 443 279 | else: 280 | self.__port = 80 281 | netloc = uri[1] 282 | if "@" in netloc: 283 | netloc = netloc.split("@", 1)[1] 284 | if ":" in netloc: 285 | netloc = netloc.split(":", 1) 286 | self.__port = int(netloc[1]) 287 | netloc = netloc[0] 288 | self.__host = netloc.lower() 289 | if self.__host == 'localhost': 290 | self.__ip = '127.0.0.1' 291 | else: 292 | self.__ip = self.__host 293 | self.__path = uri[2] 294 | self.__query = uri[-2] 295 | self.__fragment = uri[-1] 296 | 297 | def setProxy(self, host, port = None): 298 | if host == None: 299 | self.__proxy = None 300 | else: 301 | proxy = urlparse.urlsplit(host) 302 | scheme = proxy[0] 303 | if port == None: 304 | if self.__scheme == 'https': 305 | port = 443 306 | else: 307 | port = 80 308 | netloc = proxy[1] 309 | if "@" in netloc: 310 | netloc = netloc.split("@", 1)[1] 311 | if ":" in netloc: 312 | netloc = netloc.split(":", 1) 313 | port = int(netloc[1]) 314 | netloc = netloc[0] 315 | host = netloc.lower() 316 | if host == 'localhost': 317 | ip = '127.0.0.1' 318 | else: 319 | ip = host 320 | self.__proxy = {'scheme': scheme, 'host': host, 'ip':ip, 'port': port} 321 | 322 | proxy = property(fset = setProxy) 323 | 324 | def setHeader(self, name, value): 325 | lname = name.lower() 326 | if (lname != 'content-type' and 327 | lname != 'content-length' and 328 | lname != 'host'): 329 | if value: 330 | self.__header[name] = value 331 | else: 332 | del self.__header[name] 333 | 334 | def __getconnect_old(self): 335 | if self.__proxy == None: 336 | if self.__scheme == 'https': 337 | httpclient = httplib.HTTPSConnection(self.__ip, self.__port) 338 | else: 339 | httpclient = httplib.HTTPConnection(self.__ip, self.__port) 340 | else: 341 | if self.__proxy['scheme'] == 'https': 342 | httpclient = httplib.HTTPSConnection(self.__proxy['ip'], self.__proxy['port']) 343 | else: 344 | httpclient = httplib.HTTPConnection(self.__proxy['ip'], self.__proxy['port']) 345 | return httpclient 346 | 347 | def __getconnect_new(self): 348 | if self.__proxy == None: 349 | if self.__scheme == 'https': 350 | httpclient = httplib.HTTPSConnection(self.__ip, self.__port, timeout = self.timeout) 351 | else: 352 | httpclient = httplib.HTTPConnection(self.__ip, self.__port, timeout = self.timeout) 353 | else: 354 | if self.__proxy['scheme'] == 'https': 355 | httpclient = httplib.HTTPSConnection(self.__proxy['ip'], self.__proxy['port'], timeout = self.timeout) 356 | else: 357 | httpclient = httplib.HTTPConnection(self.__proxy['ip'], self.__proxy['port'], timeout = self.timeout) 358 | return httpclient 359 | 360 | if httplib.HTTPConnection.__init__.func_code.co_argcount == 4: 361 | __getconnect = __getconnect_old 362 | else: 363 | __getconnect = __getconnect_new 364 | 365 | def __getconn(self): 366 | if not self.keepAlive: 367 | return self.__getconnect() 368 | if self.__conn == None: 369 | self.__conn = self.__getconnect() 370 | return self.__conn 371 | 372 | def _sendAndReceive(self, data): 373 | header = {'Content-Type': 'application/hprose'} 374 | header['Host'] = self.__host 375 | if (self.__port != 80): 376 | header['Host'] += ':' + str(self.__port) 377 | cookie = _getCookie(self.__host, self.__path, self.__scheme == 'https') 378 | if cookie != '': 379 | header['Cookie'] = cookie 380 | if self.keepAlive: 381 | header['Connection'] = 'keep-alive' 382 | header['Keep-Alive'] = str(self.keepAliveTimeout) 383 | else: 384 | header['Connection'] = 'close' 385 | for name in self.__header: header[name] = self.__header[name] 386 | httpclient = self.__getconn() 387 | if self.__proxy == None: 388 | path = urlparse.urlunsplit(('', '', self.__path, self.__query, self.__fragment)) 389 | else: 390 | path = self._uri 391 | httpclient.request('POST', path, data, header) 392 | resp = httpclient.getresponse() 393 | if resp.status == 200: 394 | cookieList = resp.getheader('set-cookie', '').split(',') 395 | cookieList.extend(resp.getheader('set-cookie2', '').split(',')) 396 | _setCookie(cookieList, self.__host) 397 | data = resp.read() 398 | if not self.keepAlive: 399 | httpclient.close() 400 | return data 401 | else: 402 | if not self.keepAlive: 403 | httpclient.close() 404 | raise HproseException, '%d:%s' % (resp.status, resp.reason) 405 | -------------------------------------------------------------------------------- /python3/hprose/server.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/server.py # 13 | # # 14 | # hprose server for python 3.0+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import types, traceback 22 | from io import BytesIO 23 | from sys import modules, exc_info 24 | from hprose.io import HproseTags, HproseWriter, HproseReader 25 | from hprose.common import HproseResultMode, HproseException 26 | 27 | def _getInstanceMethods(cls): 28 | v = vars(cls) 29 | return [name for name in v if isinstance(v[name], types.FunctionType)] 30 | 31 | def _getClassMethods(cls): 32 | v = vars(cls) 33 | return [name for name in v if isinstance(v[name], classmethod)] 34 | 35 | def _getStaticMethods(cls): 36 | v = vars(cls) 37 | return [name for name in v if isinstance(v[name], staticmethod)] 38 | 39 | class HproseService(object): 40 | def __init__(self): 41 | self.__functions = {} 42 | self.__funcNames = {} 43 | self.__resultMode = {} 44 | self.__simpleMode = {} 45 | self.__filters = [] 46 | self.debug = False 47 | self.simple = False 48 | self.onBeforeInvoke = None 49 | self.onAfterInvoke = None 50 | self.onSendHeader = None 51 | self.onSendError = None 52 | 53 | def getFilter(self): 54 | if (len(self.__filters) == 0): 55 | return None 56 | return self.__filters[0] 57 | 58 | def setFilter(self, _filter): 59 | self.__filters = [] 60 | if _filter != None: 61 | self.__filters.append(_filter) 62 | 63 | filter = property(fget = getFilter, fset = setFilter) 64 | 65 | def addFilter(self, _filter): 66 | self.__filters.append(_filter) 67 | 68 | def removeFilter(self, _filter): 69 | self.__filters.remove(_filter) 70 | 71 | def __inputFilter(self, data, context): 72 | for _filter in reversed(self.__filters): 73 | data = _filter.inputFilter(data, context) 74 | return data 75 | 76 | def __outputFilter(self, data, context): 77 | for _filter in self.__filters: 78 | data = _filter.outputFilter(data, context) 79 | return data 80 | 81 | def _responseEnd(self, ostream, context): 82 | data = self.__outputFilter(ostream.getvalue(), context) 83 | ostream.close() 84 | return data 85 | 86 | def _fixArgs(self, args, function, context): 87 | if hasattr(function, '__code__'): 88 | fc = function.__code__ 89 | c = fc.co_argcount 90 | if (len(args) + 1 == c) and (c > 0) and (fc.co_varnames[c - 1] == 'context'): 91 | args.append(context) 92 | return args 93 | 94 | def _fireBeforeInvokeEvent(self, name, args, byref, context): 95 | if self.onBeforeInvoke != None: 96 | if hasattr(self.onBeforeInvoke, '__code__'): 97 | argcount = self.onBeforeInvoke.__code__.co_argcount 98 | if argcount == 4: 99 | self.onBeforeInvoke(name, args, byref, context) 100 | elif argcount == 3: 101 | self.onBeforeInvoke(name, args, byref) 102 | elif argcount == 2: 103 | self.onBeforeInvoke(name, args) 104 | elif argcount == 1: 105 | self.onBeforeInvoke(name) 106 | elif argcount == 0: 107 | self.onBeforeInvoke() 108 | else: 109 | self.onBeforeInvoke(name, args, byref, context) 110 | 111 | def _fireAfterInvokeEvent(self, name, args, byref, result, context): 112 | if self.onAfterInvoke != None: 113 | if hasattr(self.onAfterInvoke, '__code__'): 114 | argcount = self.onAfterInvoke.__code__.co_argcount 115 | if argcount == 5: 116 | self.onAfterInvoke(name, args, byref, result, context) 117 | elif argcount == 4: 118 | self.onAfterInvoke(name, args, byref, result) 119 | elif argcount == 3: 120 | self.onAfterInvoke(name, args, byref) 121 | elif argcount == 2: 122 | self.onAfterInvoke(name, args) 123 | elif argcount == 1: 124 | self.onAfterInvoke(name) 125 | elif argcount == 0: 126 | self.onAfterInvoke() 127 | else: 128 | self.onAfterInvoke(name, args, byref, result, context) 129 | 130 | def _fireErrorEvent(self, e, context): 131 | if self.onSendError != None: 132 | if hasattr(self.onSendError, '__code__'): 133 | argcount = self.onSendError.__code__.co_argcount 134 | if argcount == 2: 135 | self.onSendError(e, context) 136 | elif argcount == 1: 137 | self.onSendError(e) 138 | elif argcount == 0: 139 | self.onSendError() 140 | else: 141 | self.onSendError(e, context) 142 | 143 | def _doError(self, e, context): 144 | self._fireErrorEvent(e, context) 145 | if self.debug: 146 | e = ''.join(traceback.format_exception(*exc_info())) 147 | ostream = BytesIO() 148 | writer = HproseWriter(ostream, True) 149 | ostream.write(HproseTags.TagError) 150 | writer.writeString(str(e).encode('utf-8')) 151 | ostream.write(HproseTags.TagEnd) 152 | return self._responseEnd(ostream, context) 153 | 154 | def _doInvoke(self, istream, context): 155 | simpleReader = HproseReader(istream, True) 156 | tag = HproseTags.TagCall 157 | while tag == HproseTags.TagCall: 158 | name = simpleReader.readString() 159 | aliasname = name.lower() 160 | args = [] 161 | byref = False 162 | tag = simpleReader.checkTags((HproseTags.TagList, 163 | HproseTags.TagEnd, 164 | HproseTags.TagCall)) 165 | if tag == HproseTags.TagList: 166 | reader = HproseReader(istream) 167 | args = reader.readListWithoutTag() 168 | tag = reader.checkTags((HproseTags.TagTrue, 169 | HproseTags.TagEnd, 170 | HproseTags.TagCall)) 171 | if (tag == HproseTags.TagTrue): 172 | byref = True 173 | tag = reader.checkTags((HproseTags.TagEnd, 174 | HproseTags.TagCall)) 175 | self._fireBeforeInvokeEvent(name, args, byref, context) 176 | if aliasname in self.__functions: 177 | function = self.__functions[aliasname] 178 | resultMode = self.__resultMode[aliasname] 179 | simple = self.__simpleMode[aliasname] 180 | result = function(*self._fixArgs(args, function, context)) 181 | elif '*' in self.__functions: 182 | function = self.__functions['*'] 183 | resultMode = self.__resultMode['*'] 184 | simple = self.__simpleMode['*'] 185 | result = function(name, args) 186 | else: 187 | raise HproseException("Can't find this function %s()." % name) 188 | self._fireAfterInvokeEvent(name, args, byref, result, context) 189 | ostream = BytesIO() 190 | if resultMode == HproseResultMode.RawWithEndTag: 191 | return self.__outputFilter(result, context) 192 | if resultMode == HproseResultMode.Raw: 193 | ostream.write(result) 194 | else: 195 | ostream.write(HproseTags.TagResult) 196 | if resultMode == HproseResultMode.Serialized: 197 | ostream.write(result) 198 | else: 199 | if simple == None: simple = self.simple 200 | writer = HproseWriter(ostream, simple) 201 | writer.serialize(result) 202 | if byref: 203 | ostream.write(HproseTags.TagArgument) 204 | writer.reset() 205 | writer.writeList(args) 206 | ostream.write(HproseTags.TagEnd) 207 | return self._responseEnd(ostream, context) 208 | 209 | def _doFunctionList(self, context): 210 | ostream = BytesIO() 211 | writer = HproseWriter(ostream, True) 212 | ostream.write(HproseTags.TagFunctions) 213 | writer.writeView(self.__funcNames.values()) 214 | ostream.write(HproseTags.TagEnd) 215 | return self._responseEnd(ostream, context) 216 | 217 | def _handle(self, data, context): 218 | istream = None 219 | try: 220 | data = self.__inputFilter(data, context) 221 | if data == None or data == b'' or data[len(data) - 1:] != HproseTags.TagEnd: 222 | raise HproseException("Wrong Request: \r\n%s" % str(data, 'utf-8')) 223 | istream = BytesIO(data) 224 | tag = istream.read(1) 225 | if tag == HproseTags.TagCall: 226 | return self._doInvoke(istream, context) 227 | elif tag == HproseTags.TagEnd: 228 | return self._doFunctionList(context) 229 | else: 230 | raise HproseException("Wrong Request: \r\n%s" % str(data, 'utf-8')) 231 | except (KeyboardInterrupt, SystemExit): 232 | raise 233 | except Exception as e: 234 | return self._doError(e, context) 235 | finally: 236 | if istream != None: istream.close() 237 | 238 | def addMissingFunction(self, function, resultMode = HproseResultMode.Normal, simple = None): 239 | self.addFunction(function, '*', resultMode, simple) 240 | 241 | def addFunction(self, function, alias = None, resultMode = HproseResultMode.Normal, simple = None): 242 | if isinstance(function, str): 243 | function = getattr(modules['__main__'], function, None) 244 | if not hasattr(function, '__call__'): 245 | raise HproseException('Argument function is not callable') 246 | if alias == None: 247 | alias = function.__name__ 248 | if isinstance(alias, str): 249 | aliasname = alias.lower() 250 | self.__functions[aliasname] = function 251 | self.__funcNames[aliasname] = alias 252 | self.__resultMode[aliasname] = resultMode 253 | self.__simpleMode[aliasname] = simple 254 | else: 255 | raise HproseException('Argument alias is not a string') 256 | 257 | def addFunctions(self, functions, aliases = None, resultMode = HproseResultMode.Normal, simple = None): 258 | aliases_is_null = (aliases == None) 259 | if not isinstance(functions, (list, tuple)): 260 | raise HproseException('Argument functions is not a list or tuple') 261 | count = len(functions) 262 | if not aliases_is_null and count != len(aliases): 263 | raise HproseException('The count of functions is not matched with aliases') 264 | for i in range(count): 265 | function = functions[i] 266 | if aliases_is_null: 267 | self.addFunction(function, None, resultMode, simple) 268 | else: 269 | self.addFunction(function, aliases[i], resultMode, simple) 270 | 271 | def addMethod(self, methodname, belongto, alias = None, resultMode = HproseResultMode.Normal, simple = None): 272 | function = getattr(belongto, methodname, None) 273 | if alias == None: 274 | self.addFunction(function, methodname, resultMode, simple) 275 | else: 276 | self.addFunction(function, alias, resultMode, simple) 277 | 278 | def addMethods(self, methods, belongto, aliases = None, resultMode = HproseResultMode.Normal, simple = None): 279 | aliases_is_null = (aliases == None) 280 | if not isinstance(methods, (list, tuple)): 281 | raise HproseException('Argument methods is not a list or tuple') 282 | if isinstance(aliases, str): 283 | aliasPrefix = aliases 284 | aliases = [aliasPrefix + '_' + name for name in methods] 285 | count = len(methods) 286 | if not aliases_is_null and count != len(aliases): 287 | raise HproseException('The count of methods is not matched with aliases') 288 | for i in range(count): 289 | method = methods[i] 290 | function = getattr(belongto, method, None) 291 | if aliases_is_null: 292 | self.addFunction(function, method, resultMode, simple) 293 | else: 294 | self.addFunction(function, aliases[i], resultMode, simple) 295 | 296 | def addInstanceMethods(self, obj, cls = None, aliasPrefix = None, resultMode = HproseResultMode.Normal, simple = None): 297 | if cls == None: cls = obj.__class__ 298 | self.addMethods(_getInstanceMethods(cls), obj, aliasPrefix, resultMode, simple) 299 | 300 | 301 | def addClassMethods(self, cls, execcls = None, aliasPrefix = None, resultMode = HproseResultMode.Normal, simple = None): 302 | if execcls == None: execcls = cls 303 | self.addMethods(_getClassMethods(cls), execcls, aliasPrefix, resultMode, simple) 304 | 305 | def addStaticMethods(self, cls, aliasPrefix = None, resultMode = HproseResultMode.Normal, simple = None): 306 | self.addMethods(_getStaticMethods(cls), cls, aliasPrefix, resultMode, simple) 307 | 308 | def add(self, *args): 309 | args_num = len(args) 310 | if args_num == 1: 311 | if isinstance(args[0], (tuple, list)): 312 | self.addFunctions(args[0]) 313 | elif isinstance(args[0], type): 314 | self.addClassMethods(args[0]) 315 | self.addStaticMethods(args[0]) 316 | elif hasattr(args[0], '__call__'): 317 | self.addFunction(args[0]) 318 | else: 319 | self.addInstanceMethods(args[0]) 320 | elif args_num == 2: 321 | if isinstance(args[0], type): 322 | if isinstance(args[1], type): 323 | self.addClassMethods(args[0], args[1]) 324 | else: 325 | self.addClassMethods(args[0], args[0], args[1]) 326 | self.addStaticMethods(args[0], args[1]) 327 | elif isinstance(args[0], str): 328 | if isinstance(args[1], str): 329 | self.addFunction(args[0], args[1]) 330 | else: 331 | self.addMethod(args[0], args[1]) 332 | elif isinstance(args[0], (tuple, list)): 333 | if isinstance(args[1], (tuple, list)): 334 | self.addFunctions(args[0], args[1]) 335 | else: 336 | self.addMethods(args[0], args[1]) 337 | elif hasattr(args[0], '__call__') and isinstance(args[1], str): 338 | self.addFunction(args[0], args[1]) 339 | elif isinstance(args[1], str): 340 | self.addInstanceMethods(args[0], None, args[1]) 341 | else: 342 | self.addInstanceMethods(args[0], args[1]) 343 | elif args_num == 3: 344 | if isinstance(args[0], str) and isinstance(args[2], str): 345 | if args[1] == None: 346 | self.addFunction(args[0], args[2]) 347 | else: 348 | self.addMethod(args[0], args[1], args[2]) 349 | elif isinstance(args[0], (tuple, list)): 350 | if isinstance(args[2], (tuple, list)) and args[1] == None: 351 | self.addFunctions(args[0], args[2]) 352 | else: 353 | self.addMethods(args[0], args[1], args[2]) 354 | elif isinstance(args[1], type) and isinstance(args[2], str): 355 | if isinstance(args[0], type): 356 | self.addClassMethods(args[0], args[1], args[2]) 357 | else: 358 | self.addInstanceMethods(args[0], args[1], args[2]) 359 | elif hasattr(args[0], '__call__') and args[1] == None and isinstance(args[2], str): 360 | self.addFunction(args[0], args[2]) 361 | else: 362 | raise HproseException('Wrong arguments') 363 | else: 364 | raise HproseException('Wrong arguments') 365 | -------------------------------------------------------------------------------- /python2/hprose/server.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/server.py # 13 | # # 14 | # hprose server for python 2.3+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import types, traceback 22 | from cStringIO import StringIO 23 | from sys import modules, exc_info 24 | from hprose.io import HproseTags, HproseReader, HproseWriter 25 | from hprose.common import HproseException, HproseResultMode 26 | 27 | def _getInstanceMethods(cls): 28 | v = vars(cls) 29 | return [name for name in v if isinstance(v[name], types.FunctionType)] 30 | 31 | def _getClassMethods(cls): 32 | v = vars(cls) 33 | return [name for name in v if isinstance(v[name], classmethod)] 34 | 35 | def _getStaticMethods(cls): 36 | v = vars(cls) 37 | return [name for name in v if isinstance(v[name], staticmethod)] 38 | 39 | class HproseService(object): 40 | def __init__(self): 41 | self.__functions = {} 42 | self.__funcNames = {} 43 | self.__resultMode = {} 44 | self.__simpleMode = {} 45 | self.__filters = [] 46 | self.debug = False 47 | self.simple = False 48 | self.onBeforeInvoke = None 49 | self.onAfterInvoke = None 50 | self.onSendHeader = None 51 | self.onSendError = None 52 | 53 | def getFilter(self): 54 | if (len(self.__filters) == 0): 55 | return None 56 | return self.__filters[0] 57 | 58 | def setFilter(self, _filter): 59 | self.__filters = [] 60 | if _filter != None: 61 | self.__filters.append(_filter) 62 | 63 | filter = property(fget = getFilter, fset = setFilter) 64 | 65 | def addFilter(self, _filter): 66 | self.__filters.append(_filter) 67 | 68 | def removeFilter(self, _filter): 69 | self.__filters.remove(_filter) 70 | 71 | def __inputFilter(self, data, context): 72 | for _filter in reversed(self.__filters): 73 | data = _filter.inputFilter(data, context) 74 | return data 75 | 76 | def __outputFilter(self, data, context): 77 | for _filter in self.__filters: 78 | data = _filter.outputFilter(data, context) 79 | return data 80 | 81 | def _responseEnd(self, ostream, context): 82 | data = self.__outputFilter(ostream.getvalue(), context) 83 | ostream.close() 84 | return data 85 | 86 | def _fixArgs(self, args, function, context): 87 | if hasattr(function, 'func_code'): 88 | fc = function.func_code 89 | c = fc.co_argcount 90 | if (len(args) + 1 == c) and (c > 0) and (fc.co_varnames[c - 1] == 'context'): 91 | args.append(context) 92 | return args 93 | 94 | def _fireBeforeInvokeEvent(self, name, args, byref, context): 95 | if self.onBeforeInvoke != None: 96 | if hasattr(self.onBeforeInvoke, 'func_code'): 97 | argcount = self.onBeforeInvoke.func_code.co_argcount 98 | if argcount == 4: 99 | self.onBeforeInvoke(name, args, byref, context) 100 | elif argcount == 3: 101 | self.onBeforeInvoke(name, args, byref) 102 | elif argcount == 2: 103 | self.onBeforeInvoke(name, args) 104 | elif argcount == 1: 105 | self.onBeforeInvoke(name) 106 | elif argcount == 0: 107 | self.onBeforeInvoke() 108 | else: 109 | self.onBeforeInvoke(name, args, byref, context) 110 | 111 | def _fireAfterInvokeEvent(self, name, args, byref, result, context): 112 | if self.onAfterInvoke != None: 113 | if hasattr(self.onAfterInvoke, 'func_code'): 114 | argcount = self.onAfterInvoke.func_code.co_argcount 115 | if argcount == 5: 116 | self.onAfterInvoke(name, args, byref, result, context) 117 | elif argcount == 4: 118 | self.onAfterInvoke(name, args, byref, result) 119 | elif argcount == 3: 120 | self.onAfterInvoke(name, args, byref) 121 | elif argcount == 2: 122 | self.onAfterInvoke(name, args) 123 | elif argcount == 1: 124 | self.onAfterInvoke(name) 125 | elif argcount == 0: 126 | self.onAfterInvoke() 127 | else: 128 | self.onAfterInvoke(name, args, byref, result, context) 129 | 130 | def _fireErrorEvent(self, e, context): 131 | if self.onSendError != None: 132 | if hasattr(self.onSendError, 'func_code'): 133 | argcount = self.onSendError.func_code.co_argcount 134 | if argcount == 2: 135 | self.onSendError(e, context) 136 | elif argcount == 1: 137 | self.onSendError(e) 138 | elif argcount == 0: 139 | self.onSendError() 140 | else: 141 | self.onSendError(e, context) 142 | 143 | def _doError(self, e, context): 144 | self._fireErrorEvent(e, context) 145 | if self.debug: 146 | e = ''.join(traceback.format_exception(*exc_info())) 147 | ostream = StringIO() 148 | writer = HproseWriter(ostream, True) 149 | ostream.write(HproseTags.TagError) 150 | writer.writeString(str(e).encode('utf-8')) 151 | ostream.write(HproseTags.TagEnd) 152 | return self._responseEnd(ostream, context) 153 | 154 | def _doInvoke(self, istream, context): 155 | simpleReader = HproseReader(istream, True) 156 | tag = HproseTags.TagCall 157 | while tag == HproseTags.TagCall: 158 | name = simpleReader.readString() 159 | aliasname = name.lower() 160 | if isinstance(aliasname, str): 161 | aliasname = unicode(aliasname, 'utf-8') 162 | args = [] 163 | byref = False 164 | tag = simpleReader.checkTags((HproseTags.TagList, 165 | HproseTags.TagEnd, 166 | HproseTags.TagCall)) 167 | if tag == HproseTags.TagList: 168 | reader = HproseReader(istream) 169 | args = reader.readListWithoutTag() 170 | tag = reader.checkTags((HproseTags.TagTrue, 171 | HproseTags.TagEnd, 172 | HproseTags.TagCall)) 173 | if (tag == HproseTags.TagTrue): 174 | byref = True 175 | tag = reader.checkTags((HproseTags.TagEnd, 176 | HproseTags.TagCall)) 177 | self._fireBeforeInvokeEvent(name, args, byref, context) 178 | if aliasname in self.__functions: 179 | function = self.__functions[aliasname] 180 | resultMode = self.__resultMode[aliasname] 181 | simple = self.__simpleMode[aliasname] 182 | result = function(*self._fixArgs(args, function, context)) 183 | elif u'*' in self.__functions: 184 | function = self.__functions[u'*'] 185 | resultMode = self.__resultMode[u'*'] 186 | simple = self.__simpleMode[u'*'] 187 | result = function(name, args) 188 | else: 189 | raise HproseException, "Can't find this function %s()." % name 190 | self._fireAfterInvokeEvent(name, args, byref, result, context) 191 | ostream = StringIO() 192 | if resultMode == HproseResultMode.RawWithEndTag: 193 | return self.__outputFilter(result, context) 194 | if resultMode == HproseResultMode.Raw: 195 | ostream.write(result) 196 | else: 197 | ostream.write(HproseTags.TagResult) 198 | if resultMode == HproseResultMode.Serialized: 199 | ostream.write(result) 200 | else: 201 | if simple == None: simple = self.simple 202 | writer = HproseWriter(ostream, simple) 203 | writer.serialize(result) 204 | if byref: 205 | ostream.write(HproseTags.TagArgument) 206 | writer.reset() 207 | writer.writeList(args) 208 | ostream.write(HproseTags.TagEnd) 209 | return self._responseEnd(ostream, context) 210 | 211 | def _doFunctionList(self, context): 212 | ostream = StringIO() 213 | writer = HproseWriter(ostream, True) 214 | ostream.write(HproseTags.TagFunctions) 215 | writer.writeList(self.__funcNames.values()) 216 | ostream.write(HproseTags.TagEnd) 217 | return self._responseEnd(ostream, context) 218 | 219 | def _handle(self, data, context): 220 | istream = None 221 | try: 222 | data = self.__inputFilter(data, context) 223 | if data == None or data == '' or data[len(data) - 1] != HproseTags.TagEnd: 224 | raise HproseException, "Wrong Request: \r\n%s" % data 225 | istream = StringIO(data) 226 | tag = istream.read(1) 227 | if tag == HproseTags.TagCall: 228 | return self._doInvoke(istream, context) 229 | elif tag == HproseTags.TagEnd: 230 | return self._doFunctionList(context) 231 | else: 232 | raise HproseException, "Wrong Request: \r\n%s" % data 233 | except (KeyboardInterrupt, SystemExit): 234 | raise 235 | except Exception, e: 236 | return self._doError(e, context) 237 | 238 | def addMissingFunction(self, function, resultMode = HproseResultMode.Normal, simple = None): 239 | self.addFunction(function, u'*', resultMode, simple) 240 | 241 | def addFunction(self, function, alias = None, resultMode = HproseResultMode.Normal, simple = None): 242 | if isinstance(function, (str, unicode)): 243 | function = getattr(modules['__main__'], function, None) 244 | if not callable(function): 245 | raise HproseException, 'Argument function is not callable' 246 | if alias == None: 247 | alias = function.__name__ 248 | if isinstance(alias, str): 249 | alias = unicode(alias, 'utf-8') 250 | if isinstance(alias, unicode): 251 | aliasname = alias.lower() 252 | self.__functions[aliasname] = function 253 | self.__funcNames[aliasname] = alias 254 | self.__resultMode[aliasname] = resultMode 255 | self.__simpleMode[aliasname] = simple 256 | else: 257 | raise HproseException, 'Argument alias is not a string' 258 | 259 | def addFunctions(self, functions, aliases = None, resultMode = HproseResultMode.Normal, simple = None): 260 | aliases_is_null = (aliases == None) 261 | if not isinstance(functions, (list, tuple)): 262 | raise HproseException, 'Argument functions is not a list or tuple' 263 | count = len(functions) 264 | if not aliases_is_null and count != len(aliases): 265 | raise HproseException, 'The count of functions is not matched with aliases' 266 | for i in xrange(count): 267 | function = functions[i] 268 | if aliases_is_null: 269 | self.addFunction(function, None, resultMode, simple) 270 | else: 271 | self.addFunction(function, aliases[i], resultMode, simple) 272 | 273 | def addMethod(self, methodname, belongto, alias = None, resultMode = HproseResultMode.Normal, simple = None): 274 | function = getattr(belongto, methodname, None) 275 | if alias == None: 276 | self.addFunction(function, methodname, resultMode, simple) 277 | else: 278 | self.addFunction(function, alias, resultMode, simple) 279 | 280 | def addMethods(self, methods, belongto, aliases = None, resultMode = HproseResultMode.Normal, simple = None): 281 | aliases_is_null = (aliases == None) 282 | if not isinstance(methods, (list, tuple)): 283 | raise HproseException, 'Argument methods is not a list or tuple' 284 | if isinstance(aliases, (str, unicode)): 285 | if isinstance(aliases, str): 286 | aliasPrefix = aliases 287 | else: 288 | aliasPrefix = aliases.encode('utf-8') 289 | aliases = [aliasPrefix + '_' + name for name in methods] 290 | count = len(methods) 291 | if not aliases_is_null and count != len(aliases): 292 | raise HproseException, 'The count of methods is not matched with aliases' 293 | for i in xrange(count): 294 | method = methods[i] 295 | function = getattr(belongto, method, None) 296 | if aliases_is_null: 297 | self.addFunction(function, method, resultMode, simple) 298 | else: 299 | self.addFunction(function, aliases[i], resultMode, simple) 300 | 301 | def addInstanceMethods(self, obj, cls = None, aliasPrefix = None, resultMode = HproseResultMode.Normal, simple = None): 302 | if cls == None: cls = obj.__class__ 303 | self.addMethods(_getInstanceMethods(cls), obj, aliasPrefix, resultMode, simple) 304 | 305 | def addClassMethods(self, cls, execcls = None, aliasPrefix = None, resultMode = HproseResultMode.Normal, simple = None): 306 | if execcls == None: execcls = cls 307 | self.addMethods(_getClassMethods(cls), execcls, aliasPrefix, resultMode, simple) 308 | 309 | def addStaticMethods(self, cls, aliasPrefix = None, resultMode = HproseResultMode.Normal, simple = None): 310 | self.addMethods(_getStaticMethods(cls), cls, aliasPrefix, resultMode, simple) 311 | 312 | def add(self, *args): 313 | args_num = len(args) 314 | if args_num == 1: 315 | if isinstance(args[0], (tuple, list)): 316 | self.addFunctions(args[0]) 317 | elif isinstance(args[0], (types.TypeType, types.ClassType)): 318 | self.addClassMethods(args[0]) 319 | self.addStaticMethods(args[0]) 320 | elif callable(args[0]): 321 | self.addFunction(args[0]) 322 | else: 323 | self.addInstanceMethods(args[0]) 324 | elif args_num == 2: 325 | if isinstance(args[0], (types.TypeType, types.ClassType)): 326 | if isinstance(args[1], (types.TypeType, types.ClassType)): 327 | self.addClassMethods(args[0], args[1]) 328 | else: 329 | self.addClassMethods(args[0], args[0], args[1]) 330 | self.addStaticMethods(args[0], args[1]) 331 | elif isinstance(args[0], (str, unicode)): 332 | if isinstance(args[1], (str, unicode)): 333 | self.addFunction(args[0], args[1]) 334 | else: 335 | self.addMethod(args[0], args[1]) 336 | elif isinstance(args[0], (tuple, list)): 337 | if isinstance(args[1], (tuple, list)): 338 | self.addFunctions(args[0], args[1]) 339 | else: 340 | self.addMethods(args[0], args[1]) 341 | elif callable(args[0]) and isinstance(args[1], (str, unicode)): 342 | self.addFunction(args[0], args[1]) 343 | elif isinstance(args[1], (str, unicode)): 344 | self.addInstanceMethods(args[0], None, args[1]) 345 | else: 346 | self.addInstanceMethods(args[0], args[1]) 347 | elif args_num == 3: 348 | if isinstance(args[0], (str, unicode)) and isinstance(args[2], (str, unicode)): 349 | if args[1] == None: 350 | self.addFunction(args[0], args[2]) 351 | else: 352 | self.addMethod(args[0], args[1], args[2]) 353 | elif isinstance(args[0], (tuple, list)): 354 | if isinstance(args[2], (tuple, list)) and args[1] == None: 355 | self.addFunctions(args[0], args[2]) 356 | else: 357 | self.addMethods(args[0], args[1], args[2]) 358 | elif isinstance(args[1], (types.ClassType, types.TypeType)) and isinstance(args[2], (str, unicode)): 359 | if isinstance(args[0], (types.ClassType, types.TypeType)): 360 | self.addClassMethods(args[0], args[1], args[2]) 361 | else: 362 | self.addInstanceMethods(args[0], args[1], args[2]) 363 | elif callable(args[0]) and args[1] == None and isinstance(args[2], (str, unicode)): 364 | self.addFunction(args[0], args[2]) 365 | else: 366 | raise HproseException, 'Wrong arguments' 367 | else: 368 | raise HproseException, 'Wrong arguments' 369 | -------------------------------------------------------------------------------- /python3/hprose/io.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/io.py # 13 | # # 14 | # hprose io for python 3.0+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | import datetime 22 | from io import BytesIO 23 | from fpconst import NaN, PosInf, NegInf, isInf, isNaN, isPosInf 24 | from inspect import isclass 25 | from sys import modules 26 | from threading import RLock 27 | from uuid import UUID 28 | from hprose.common import HproseException 29 | import decimal 30 | 31 | ZERO = datetime.timedelta(0) 32 | 33 | class UTC(datetime.tzinfo): 34 | def utcoffset(self, dt): 35 | return ZERO 36 | def tzname(self, dt): 37 | return "UTC" 38 | def dst(self, dt): 39 | return ZERO 40 | utc = UTC() 41 | 42 | class HproseTags: 43 | # Serialize Tags # 44 | TagInteger = b'i' 45 | TagLong = b'l' 46 | TagDouble = b'd' 47 | TagNull = b'n' 48 | TagEmpty = b'e' 49 | TagTrue = b't' 50 | TagFalse = b'f' 51 | TagNaN = b'N' 52 | TagInfinity = b'I' 53 | TagDate = b'D' 54 | TagTime = b'T' 55 | TagUTC = b'Z' 56 | TagBytes = b'b' 57 | TagUTF8Char = b'u' 58 | TagString = b's' 59 | TagGuid = b'g' 60 | TagList = b'a' 61 | TagMap = b'm' 62 | TagClass = b'c' 63 | TagObject = b'o' 64 | TagRef = b'r' 65 | # Serialize Marks # 66 | TagPos = b'+' 67 | TagNeg = b'-' 68 | TagSemicolon = b';' 69 | TagOpenbrace = b'{' 70 | TagClosebrace = b'}' 71 | TagQuote = b'"' 72 | TagPoint = b'.' 73 | # Protocol Tags # 74 | TagFunctions = b'F' 75 | TagCall = b'C' 76 | TagResult = b'R' 77 | TagArgument = b'A' 78 | TagError = b'E' 79 | TagEnd = b'z' 80 | 81 | _classCache1 = {} 82 | _classCache2 = {} 83 | _classCacheLock = RLock() 84 | 85 | def _get_class(name): 86 | name = name.split('.') 87 | if len(name) == 1: 88 | return getattr(modules['__main__'], name[0], None) 89 | clsname = name.pop() 90 | modname = '.'.join(name) 91 | if modname in modules: 92 | return getattr(modules[modname], clsname, None) 93 | return None 94 | 95 | def _get_class2(name, ps, i, c): 96 | if i < len(ps): 97 | p = ps[i] 98 | name = name[:p] + c + name[p + 1:] 99 | cls = _get_class2(name, ps, i + 1, '.') 100 | if (i + 1 < len(ps)) and (cls == None): 101 | cls = _get_class2(name, ps, i + 1, '_') 102 | return cls 103 | return _get_class(name) 104 | 105 | def _get_class_by_alias(name): 106 | cls = getattr(modules['__main__'], name, None) 107 | if not isclass(cls): 108 | ps = [] 109 | p = name.find('_') 110 | while p > -1: 111 | ps.append(p) 112 | p = name.find('_', p + 1) 113 | cls = _get_class2(name, ps, 0, '.') 114 | if cls == None: 115 | cls = _get_class2(name, ps, 0, '_') 116 | if cls == None: 117 | cls = type(name, (), {}) 118 | cls.__module__ = '__main__' 119 | setattr(modules['__main__'], name, cls) 120 | return cls 121 | 122 | class HproseClassManager: 123 | def register(_class, alias): 124 | _classCacheLock.acquire() 125 | try: 126 | _classCache1[_class] = alias 127 | _classCache2[alias] = _class 128 | finally: 129 | _classCacheLock.release() 130 | register = staticmethod(register) 131 | 132 | def getClass(alias): 133 | if alias in _classCache2: 134 | return _classCache2[alias] 135 | _class = _get_class_by_alias(alias) 136 | HproseClassManager.register(_class, alias) 137 | return _class 138 | getClass = staticmethod(getClass) 139 | 140 | def getClassAlias(_class): 141 | if _class in _classCache1: 142 | return _classCache1[_class] 143 | alias = [] 144 | if _class.__module__ != '__main__': 145 | alias.extend(_class.__module__.split('.')) 146 | alias.append(_class.__name__) 147 | alias = '_'.join(alias) 148 | HproseClassManager.register(_class, alias) 149 | return alias 150 | getClassAlias = staticmethod(getClassAlias) 151 | 152 | def _readuntil(stream, char): 153 | a = [] 154 | while True: 155 | c = stream.read(1) 156 | if (c == char) or (c == b''): break 157 | a.append(c) 158 | return b''.join(a) 159 | 160 | def _readint(stream, char): 161 | s = _readuntil(stream, char) 162 | if s == b'': return 0 163 | return int(s, 10) 164 | 165 | class HproseRawReader(object): 166 | def __init__(self, stream): 167 | self.stream = stream 168 | def unexpectedTag(self, tag, expectTags = None): 169 | if tag == b'': 170 | raise HproseException('No byte found in stream') 171 | elif expectTags == None: 172 | raise HproseException( 173 | "Unexpected serialize tag '%s' in stream" % 174 | str(tag, 'utf-8')) 175 | else: 176 | raise HproseException( 177 | "Tag '%s' expected, but '%s' found in stream" % 178 | (str(expectTags, 'utf-8'), str(tag, 'utf-8'))) 179 | def readRaw(self, ostream = None, tag = None): 180 | if ostream == None: 181 | ostream = BytesIO() 182 | if tag == None: 183 | tag = self.stream.read(1) 184 | ostream.write(tag) 185 | if ((b'0' <= tag <= b'9') or 186 | (tag == HproseTags.TagNull) or 187 | (tag == HproseTags.TagEmpty) or 188 | (tag == HproseTags.TagTrue) or 189 | (tag == HproseTags.TagFalse) or 190 | (tag == HproseTags.TagNaN)): 191 | pass 192 | elif tag == HproseTags.TagInfinity: 193 | ostream.write(self.stream.read(1)) 194 | elif ((tag == HproseTags.TagInteger) or 195 | (tag == HproseTags.TagLong) or 196 | (tag == HproseTags.TagDouble) or 197 | (tag == HproseTags.TagRef)): 198 | self.__readNumberRaw(ostream) 199 | elif ((tag == HproseTags.TagDate) or 200 | (tag == HproseTags.TagTime)): 201 | self.__readDateTimeRaw(ostream) 202 | elif (tag == HproseTags.TagUTF8Char): 203 | self.__readUTF8CharRaw(ostream) 204 | elif (tag == HproseTags.TagBytes): 205 | self.__readBytesRaw(ostream) 206 | elif (tag == HproseTags.TagString): 207 | self.__readStringRaw(ostream) 208 | elif (tag == HproseTags.TagGuid): 209 | self.__readGuidRaw(ostream) 210 | elif ((tag == HproseTags.TagList) or 211 | (tag == HproseTags.TagMap) or 212 | (tag == HproseTags.TagObject)): 213 | self.__readComplexRaw(ostream) 214 | elif (tag == HproseTags.TagClass): 215 | self.__readComplexRaw(ostream) 216 | self.readRaw(ostream) 217 | elif (tag == HproseTags.TagError): 218 | self.readRaw(ostream) 219 | else: 220 | self.unexpectedTag(tag) 221 | return ostream 222 | def __readNumberRaw(self, ostream): 223 | ostream.write(_readuntil(self.stream, HproseTags.TagSemicolon)) 224 | ostream.write(HproseTags.TagSemicolon) 225 | def __readDateTimeRaw(self, ostream): 226 | s = [] 227 | while True: 228 | c = self.stream.read(1) 229 | s.append(c) 230 | if ((c == HproseTags.TagSemicolon) or 231 | (c == HproseTags.TagUTC)): break 232 | ostream.write(b''.join(s)) 233 | def __readUTF8CharRaw(self, ostream): 234 | s = [] 235 | c = self.stream.read(1) 236 | s.append(c) 237 | a = ord(c) 238 | if (a & 0xE0) == 0xC0: 239 | s.append(self.stream.read(1)) 240 | elif (a & 0xF0) == 0xE0: 241 | s.append(self.stream.read(2)) 242 | elif a > 0x7F: 243 | raise HproseException('Bad utf-8 encoding') 244 | ostream.write(b''.join(s)) 245 | 246 | def __readBytesRaw(self, ostream): 247 | l = _readuntil(self.stream, HproseTags.TagQuote) 248 | ostream.write(l) 249 | ostream.write(HproseTags.TagQuote) 250 | if l == b'': 251 | l = 0 252 | else: 253 | l = int(l, 10) 254 | ostream.write(self.stream.read(l + 1)) 255 | 256 | def __readStringRaw(self, ostream): 257 | l = _readuntil(self.stream, HproseTags.TagQuote) 258 | ostream.write(l) 259 | ostream.write(HproseTags.TagQuote) 260 | if l == b'': 261 | l = 0 262 | else: 263 | l = int(l, 10) 264 | s = [] 265 | i = 0 266 | while i < l: 267 | c = self.stream.read(1) 268 | s.append(c) 269 | a = ord(c) 270 | if (a & 0xE0) == 0xC0: 271 | s.append(self.stream.read(1)) 272 | elif (a & 0xF0) == 0xE0: 273 | s.append(self.stream.read(2)) 274 | elif (a & 0xF8) == 0xF0: 275 | s.append(self.stream.read(3)) 276 | i += 1 277 | i += 1 278 | s.append(self.stream.read(1)) 279 | ostream.write(b''.join(s)) 280 | def __readGuidRaw(self, ostream): 281 | ostream.write(self.stream.read(38)) 282 | def __readComplexRaw(self, ostream): 283 | ostream.write(_readuntil(self.stream, HproseTags.TagOpenbrace)) 284 | ostream.write(HproseTags.TagOpenbrace) 285 | tag = self.stream.read(1) 286 | while tag != HproseTags.TagClosebrace: 287 | self.readRaw(ostream, tag) 288 | tag = self.stream.read(1) 289 | ostream.write(tag) 290 | 291 | class FakeReaderRefer: 292 | def set(self, val): 293 | pass 294 | def read(self, index): 295 | raise HproseException( 296 | "Unexpected serialize tag '%s' in stream" % 297 | str(HproseTags.TagRef, 'utf-8')) 298 | def reset(self): 299 | pass 300 | 301 | class RealReaderRefer: 302 | def __init__(self): 303 | self.ref = [] 304 | def set(self, val): 305 | self.ref.append(val) 306 | def read(self, index): 307 | return self.ref[index] 308 | def reset(self): 309 | del self.ref[:] 310 | 311 | class HproseReader(HproseRawReader): 312 | def __init__(self, stream, simple = False): 313 | super(HproseReader, self).__init__(stream) 314 | self.refer = FakeReaderRefer() if simple else RealReaderRefer() 315 | self.classref = [] 316 | def unserialize(self): 317 | tag = self.stream.read(1) 318 | if b'0' <= tag <= b'9': 319 | return int(tag, 10) 320 | if (tag == HproseTags.TagInteger or 321 | tag == HproseTags.TagLong): 322 | return self.__readIntegerWithoutTag() 323 | if tag == HproseTags.TagDouble: 324 | return self.__readDoubleWithoutTag() 325 | if tag == HproseTags.TagNull: 326 | return None 327 | if tag == HproseTags.TagEmpty: 328 | return '' 329 | if tag == HproseTags.TagTrue: 330 | return True 331 | if tag == HproseTags.TagFalse: 332 | return False 333 | if tag == HproseTags.TagNaN: 334 | return NaN 335 | if tag == HproseTags.TagInfinity: 336 | return self.__readInfinityWithoutTag() 337 | if tag == HproseTags.TagDate: 338 | return self.readDateWithoutTag() 339 | if tag == HproseTags.TagTime: 340 | return self.readTimeWithoutTag() 341 | if tag == HproseTags.TagBytes: 342 | return self.readBytesWithoutTag() 343 | if tag == HproseTags.TagUTF8Char: 344 | return self.__readUTF8CharWithoutTag() 345 | if tag == HproseTags.TagString: 346 | return self.readStringWithoutTag() 347 | if tag == HproseTags.TagGuid: 348 | return self.readGuidWithoutTag() 349 | if tag == HproseTags.TagList: 350 | return self.readListWithoutTag() 351 | if tag == HproseTags.TagMap: 352 | return self.readMapWithoutTag() 353 | if tag == HproseTags.TagClass: 354 | self.__readClass() 355 | return self.readObject() 356 | if tag == HproseTags.TagObject: 357 | return self.readObjectWithoutTag() 358 | if tag == HproseTags.TagRef: 359 | return self.__readRef() 360 | if tag == HproseTags.TagError: 361 | raise HproseException(self.readString()) 362 | self.unexpectedTag(tag) 363 | def checkTag(self, expectTag): 364 | tag = self.stream.read(1) 365 | if tag != expectTag: 366 | self.unexpectedTag(tag, expectTag) 367 | def checkTags(self, expectTags): 368 | tag = self.stream.read(1) 369 | if tag not in expectTags: 370 | self.unexpectedTag(tag, b''.join(expectTags)) 371 | return tag 372 | def __readIntegerWithoutTag(self): 373 | return int(_readuntil(self.stream, HproseTags.TagSemicolon), 10) 374 | def readInteger(self): 375 | tag = self.stream.read(1) 376 | if b'0' <= tag <= b'9': 377 | return int(tag, 10) 378 | if (tag == HproseTags.TagInteger or 379 | tag == HproseTags.TagLong): 380 | return self.__readIntegerWithoutTag() 381 | self.unexpectedTag(tag) 382 | def readLongWithoutTag(self): 383 | return self.__readIntegerWithoutTag() 384 | def readLong(self): 385 | return self.readInteger() 386 | def __readDoubleWithoutTag(self): 387 | return float(_readuntil(self.stream, HproseTags.TagSemicolon)) 388 | def readDouble(self): 389 | tag = self.stream.read(1) 390 | if b'0' <= tag <= b'9': 391 | return float(tag) 392 | if (tag == HproseTags.TagInteger or 393 | tag == HproseTags.TagLong or 394 | tag == HproseTags.TagDouble): 395 | return self.__readDoubleWithoutTag() 396 | if tag == HproseTags.TagNaN: 397 | return NaN 398 | if tag == HproseTags.TagInfinity: 399 | return self.__readInfinityWithoutTag() 400 | self.unexpectedTag(tag) 401 | def __readInfinityWithoutTag(self): 402 | if self.stream.read(1) == HproseTags.TagNeg: 403 | return NegInf 404 | else: 405 | return PosInf 406 | def readBoolean(self): 407 | tag = self.checkTags((HproseTags.TagTrue, HproseTags.TagFalse)) 408 | return tag == HproseTags.TagTrue 409 | def readDateWithoutTag(self): 410 | year = int(self.stream.read(4), 10) 411 | month = int(self.stream.read(2), 10) 412 | day = int(self.stream.read(2), 10) 413 | tag = self.stream.read(1) 414 | if tag == HproseTags.TagTime: 415 | hour = int(self.stream.read(2), 10) 416 | minute = int(self.stream.read(2), 10) 417 | second = int(self.stream.read(2), 10) 418 | (tag, microsecond) = self.__readMicrosecond() 419 | if tag == HproseTags.TagUTC: 420 | d = datetime.datetime(year, month, day, hour, minute, second, microsecond, utc) 421 | else: 422 | d = datetime.datetime(year, month, day, hour, minute, second, microsecond) 423 | elif tag == HproseTags.TagUTC: 424 | d = datetime.datetime(year, month, day, 0, 0, 0, 0, utc) 425 | else: 426 | d = datetime.date(year, month, day) 427 | self.refer.set(d) 428 | return d 429 | def readDate(self): 430 | tag = self.stream.read(1) 431 | if tag == HproseTags.TagNull: return None 432 | if tag == HproseTags.TagRef: return self.__readRef() 433 | if tag == HproseTags.TagDate: return self.readDateWithoutTag() 434 | self.unexpectedTag(tag) 435 | def readTimeWithoutTag(self): 436 | hour = int(self.stream.read(2), 10) 437 | minute = int(self.stream.read(2), 10) 438 | second = int(self.stream.read(2), 10) 439 | (tag, microsecond) = self.__readMicrosecond() 440 | if tag == HproseTags.TagUTC: 441 | t = datetime.time(hour, minute, second, microsecond, utc) 442 | else: 443 | t = datetime.time(hour, minute, second, microsecond) 444 | self.refer.set(t) 445 | return t 446 | def readTime(self): 447 | tag = self.stream.read(1) 448 | if tag == HproseTags.TagNull: return None 449 | if tag == HproseTags.TagRef: return self.__readRef() 450 | if tag == HproseTags.TagTime: return self.readTimeWithoutTag() 451 | self.unexpectedTag(tag) 452 | def readBytesWithoutTag(self): 453 | b = self.stream.read(_readint(self.stream, HproseTags.TagQuote)) 454 | self.stream.read(1) 455 | self.refer.set(b) 456 | return b 457 | def readBytes(self): 458 | tag = self.stream.read(1) 459 | if tag == HproseTags.TagNull: return None 460 | if tag == HproseTags.TagEmpty: return b'' 461 | if tag == HproseTags.TagRef: return self.__readRef() 462 | if tag == HproseTags.TagBytes: return self.readBytesWithoutTag() 463 | self.unexpectedTag(tag) 464 | def __readUTF8CharWithoutTag(self): 465 | s = [] 466 | c = self.stream.read(1) 467 | s.append(c) 468 | a = ord(c) 469 | if (a & 0xE0) == 0xC0: 470 | s.append(self.stream.read(1)) 471 | elif (a & 0xF0) == 0xE0: 472 | s.append(self.stream.read(2)) 473 | elif a > 0x7F: 474 | raise HproseException('Bad utf-8 encoding') 475 | return str(b''.join(s), 'utf-8') 476 | def __readString(self): 477 | l = _readint(self.stream, HproseTags.TagQuote) 478 | s = [] 479 | i = 0 480 | while i < l: 481 | c = self.stream.read(1) 482 | s.append(c) 483 | a = ord(c) 484 | if (a & 0xE0) == 0xC0: 485 | s.append(self.stream.read(1)) 486 | elif (a & 0xF0) == 0xE0: 487 | s.append(self.stream.read(2)) 488 | elif (a & 0xF8) == 0xF0: 489 | s.append(self.stream.read(3)) 490 | i += 1 491 | i += 1 492 | self.stream.read(1) 493 | s = str(b''.join(s), 'utf-8') 494 | return s 495 | def readStringWithoutTag(self): 496 | s = self.__readString() 497 | self.refer.set(s) 498 | return s 499 | def readString(self): 500 | tag = self.stream.read(1) 501 | if tag == HproseTags.TagNull: return None 502 | if tag == HproseTags.TagEmpty: return '' 503 | if tag == HproseTags.TagUTF8Char: return self.__readUTF8CharWithoutTag() 504 | if tag == HproseTags.TagRef: return self.__readRef() 505 | if tag == HproseTags.TagString: return self.readStringWithoutTag() 506 | self.unexpectedTag(tag) 507 | def readGuidWithoutTag(self): 508 | u = UUID(str(self.stream.read(38), 'utf-8')) 509 | self.refer.set(u) 510 | return u 511 | def readGuid(self): 512 | tag = self.stream.read(1) 513 | if tag == HproseTags.TagNull: return None 514 | if tag == HproseTags.TagRef: return self.__readRef() 515 | if tag == HproseTags.TagGuid: return self.readGuidWithoutTag() 516 | self.unexpectedTag(tag) 517 | def readListWithoutTag(self): 518 | l = [] 519 | self.refer.set(l) 520 | c = _readint(self.stream, HproseTags.TagOpenbrace) 521 | for _ in range(c): l.append(self.unserialize()) 522 | self.stream.read(1) 523 | return l 524 | def readList(self): 525 | tag = self.stream.read(1) 526 | if tag == HproseTags.TagNull: return None 527 | if tag == HproseTags.TagRef: return self.__readRef() 528 | if tag == HproseTags.TagList: return self.readListWithoutTag() 529 | self.unexpectedTag(tag) 530 | def readMapWithoutTag(self): 531 | m = {} 532 | self.refer.set(m) 533 | c = _readint(self.stream, HproseTags.TagOpenbrace) 534 | for _ in range(c): 535 | k = self.unserialize() 536 | v = self.unserialize() 537 | m[k] = v 538 | self.stream.read(1) 539 | return m 540 | def readMap(self): 541 | tag = self.stream.read(1) 542 | if tag == HproseTags.TagNull: return None 543 | if tag == HproseTags.TagRef: return self.__readRef() 544 | if tag == HproseTags.TagMap: return self.readMapWithoutTag() 545 | self.unexpectedTag(tag) 546 | def readObjectWithoutTag(self): 547 | (cls, count, fields) = self.classref[_readint(self.stream, HproseTags.TagOpenbrace)] 548 | obj = cls() 549 | self.refer.set(obj) 550 | for i in range(count): setattr(obj, fields[i], self.unserialize()) 551 | self.stream.read(1) 552 | return obj 553 | def readObject(self): 554 | tag = self.stream.read(1) 555 | if tag == HproseTags.TagNull: return None 556 | if tag == HproseTags.TagRef: return self.__readRef() 557 | if tag == HproseTags.TagObject: return self.readObjectWithoutTag() 558 | if tag == HproseTags.TagClass: 559 | self.__readClass() 560 | return self.readObject() 561 | self.unexpectedTag(tag) 562 | def __readClass(self): 563 | classname = self.__readString() 564 | count = _readint(self.stream, HproseTags.TagOpenbrace) 565 | fields = [self.readString() for _ in range(count)] 566 | self.stream.read(1) 567 | cls = HproseClassManager.getClass(classname) 568 | self.classref.append((cls, count, fields)) 569 | def __readRef(self): 570 | return self.refer.read(_readint(self.stream, HproseTags.TagSemicolon)) 571 | def __readMicrosecond(self): 572 | microsecond = 0 573 | tag = self.stream.read(1) 574 | if tag == HproseTags.TagPoint: 575 | microsecond = int(self.stream.read(3), 10) * 1000 576 | tag = self.stream.read(1) 577 | if b'0' <= tag <= b'9': 578 | microsecond = microsecond + int(tag, 10) * 100 + int(self.stream.read(2), 10) 579 | tag = self.stream.read(1) 580 | if b'0' <= tag <= b'9': 581 | self.stream.read(2) 582 | tag = self.stream.read(1) 583 | return (tag, microsecond) 584 | def reset(self): 585 | del self.classref[:] 586 | self.refer.reset() 587 | 588 | dict_items = type({}.items()) 589 | dict_keys = type({}.keys()) 590 | dict_values = type({}.values()) 591 | 592 | class FakeWriterRefer: 593 | def set(self, val): 594 | pass 595 | def write(self, val): 596 | return False 597 | def reset(self): 598 | pass 599 | 600 | class RealWriterRefer: 601 | def __init__(self, stream): 602 | self.stream = stream 603 | self.ref = {} 604 | self.refcount = 0 605 | def set(self, val): 606 | self.ref[id(val)] = self.refcount 607 | self.refcount += 1 608 | def write(self, val): 609 | valid = id(val) 610 | if (valid in self.ref): 611 | self.stream.write(HproseTags.TagRef) 612 | self.stream.write(str(self.ref[valid]).encode('utf-8')) 613 | self.stream.write(HproseTags.TagSemicolon) 614 | return True 615 | return False 616 | def reset(self): 617 | self.ref.clear() 618 | self.refcount = 0 619 | 620 | class HproseWriter(object): 621 | def __init__(self, stream, simple = False): 622 | self.stream = stream 623 | self.classref = {} 624 | self.fieldsref = [] 625 | self.refer = FakeWriterRefer() if simple else RealWriterRefer(stream) 626 | def serialize(self, v): 627 | if v == None: self.writeNull() 628 | elif isinstance(v, bool): self.writeBoolean(v) 629 | elif isinstance(v, int): self.writeInteger(v) 630 | elif isinstance(v, float): self.writeDouble(v) 631 | elif isinstance(v, decimal.Decimal): self.writeDouble(v) 632 | elif isinstance(v, (bytes, bytearray, memoryview)): self.writeBytesWithRef(v) 633 | elif isinstance(v, str): 634 | if v == '': 635 | self.writeEmpty() 636 | elif len(v) == 1: 637 | self.writeUTF8Char(v) 638 | else: 639 | self.writeStringWithRef(v) 640 | elif isinstance(v, UUID): self.writeGuidWithRef(v) 641 | elif isinstance(v, (list, tuple)): self.writeListWithRef(v) 642 | elif isinstance(v, (dict_items, dict_keys, dict_values)): self.writeViewWithRef(v) 643 | elif isinstance(v, dict): self.writeMapWithRef(v) 644 | elif isinstance(v, (datetime.datetime, datetime.date)): self.writeDateWithRef(v) 645 | elif isinstance(v, datetime.time): self.writeTimeWithRef(v) 646 | elif isinstance(v, object): self.writeObjectWithRef(v) 647 | else: raise HproseException('Not support to serialize this data') 648 | def writeInteger(self, i): 649 | if 0 <= i <= 9: 650 | self.stream.write(str(i).encode('utf-8')) 651 | elif -2147483648 <= i <= 2147483647: 652 | self.stream.write(HproseTags.TagInteger) 653 | self.stream.write(str(i).encode('utf-8')) 654 | self.stream.write(HproseTags.TagSemicolon) 655 | else: 656 | self.writeLong(i) 657 | def writeLong(self, l): 658 | self.stream.write(HproseTags.TagLong) 659 | self.stream.write(str(l).encode('utf-8')) 660 | self.stream.write(HproseTags.TagSemicolon) 661 | def writeDouble(self, d): 662 | if isNaN(d): self.writeNaN() 663 | elif isInf(d): self.writeInfinity(isPosInf(d)) 664 | else: 665 | self.stream.write(HproseTags.TagDouble) 666 | self.stream.write(str(d).encode('utf-8')) 667 | self.stream.write(HproseTags.TagSemicolon) 668 | def writeNaN(self): 669 | self.stream.write(HproseTags.TagNaN) 670 | def writeInfinity(self, positive = True): 671 | self.stream.write(HproseTags.TagInfinity) 672 | if positive: 673 | self.stream.write(HproseTags.TagPos) 674 | else: 675 | self.stream.write(HproseTags.TagNeg) 676 | def writeNull(self): 677 | self.stream.write(HproseTags.TagNull) 678 | def writeEmpty(self): 679 | self.stream.write(HproseTags.TagEmpty) 680 | def writeBoolean(self, b): 681 | if b: 682 | self.stream.write(HproseTags.TagTrue) 683 | else: 684 | self.stream.write(HproseTags.TagFalse) 685 | def writeDate(self, date): 686 | self.refer.set(date) 687 | if isinstance(date, datetime.datetime): 688 | if (date.utcoffset() != ZERO) and (date.utcoffset() != None): 689 | date = date.astimezone(utc) 690 | if date.hour == 0 and date.minute == 0 and date.second == 0 and date.microsecond == 0: 691 | fmt = '%c%s' % (str(HproseTags.TagDate, 'utf-8'), '%Y%m%d') 692 | elif date.year == 1970 and date.month == 1 and date.day == 1: 693 | fmt = '%c%s' % (str(HproseTags.TagTime, 'utf-8'), '%H%M%S') 694 | else: 695 | fmt = '%c%s%c%s' % (str(HproseTags.TagDate, 'utf-8'), '%Y%m%d', 696 | str(HproseTags.TagTime, 'utf-8'), '%H%M%S') 697 | if date.microsecond > 0: 698 | fmt = '%s%c%s' % (fmt, str(HproseTags.TagPoint, 'utf-8'), '%f') 699 | if date.utcoffset() == ZERO: 700 | fmt = '%s%c' % (fmt, str(HproseTags.TagUTC, 'utf-8')) 701 | else: 702 | fmt = '%s%c' % (fmt, str(HproseTags.TagSemicolon, 'utf-8')) 703 | else: 704 | fmt = '%c%s%c' % (str(HproseTags.TagDate, 'utf-8'), 705 | '%Y%m%d', 706 | str(HproseTags.TagSemicolon, 'utf-8')) 707 | self.stream.write(date.strftime(fmt).encode('utf-8')) 708 | def writeDateWithRef(self, date): 709 | if not self.refer.write(date): self.writeDate(date) 710 | def writeTime(self, time): 711 | self.refer.set(time) 712 | fmt = '%c%s' % (str(HproseTags.TagTime, 'utf-8'), '%H%M%S') 713 | if time.microsecond > 0: 714 | fmt = '%s%c%s' % (fmt, str(HproseTags.TagPoint, 'utf-8'), '%f') 715 | if time.utcoffset() == ZERO: 716 | fmt = '%s%c' % (fmt, str(HproseTags.TagUTC, 'utf-8')) 717 | else: 718 | fmt = '%s%c' % (fmt, str(HproseTags.TagSemicolon, 'utf-8')) 719 | self.stream.write(time.strftime(fmt).encode('utf-8')) 720 | def writeTimeWithRef(self, time): 721 | if not self.refer.write(time): self.writeTime(time) 722 | def writeBytes(self, b): 723 | self.refer.set(b) 724 | length = len(b) 725 | self.stream.write(HproseTags.TagBytes) 726 | if length > 0: self.stream.write(str(length).encode('utf-8')) 727 | self.stream.write(HproseTags.TagQuote) 728 | if length > 0: self.stream.write(b) 729 | self.stream.write(HproseTags.TagQuote) 730 | def writeBytesWithRef(self, b): 731 | if not self.refer.write(b): self.writeBytes(b) 732 | def writeUTF8Char(self, u): 733 | self.stream.write(HproseTags.TagUTF8Char) 734 | self.stream.write(u.encode('utf-8')) 735 | def writeString(self, s): 736 | self.refer.set(s) 737 | length = len(s) 738 | if length == 0: 739 | self.stream.write(('%s%s%s' % (str(HproseTags.TagString, 'utf-8'), 740 | str(HproseTags.TagQuote, 'utf-8'), 741 | str(HproseTags.TagQuote, 'utf-8'))).encode('utf-8')) 742 | else: 743 | self.stream.write(('%s%d%s%s%s' % (str(HproseTags.TagString, 'utf-8'), 744 | length, 745 | str(HproseTags.TagQuote, 'utf-8'), 746 | s, 747 | str(HproseTags.TagQuote, 'utf-8'))).encode('utf-8')) 748 | def writeStringWithRef(self, s): 749 | if not self.refer.write(s): self.writeString(s) 750 | def writeGuid(self, guid): 751 | self.refer.set(guid) 752 | self.stream.write(HproseTags.TagGuid) 753 | self.stream.write(HproseTags.TagOpenbrace) 754 | self.stream.write(str(guid).encode('utf-8')) 755 | self.stream.write(HproseTags.TagClosebrace) 756 | def writeGuidWithRef(self, guid): 757 | if not self.refer.write(guid): self.writeGuid(guid) 758 | def writeList(self, l): 759 | self.refer.set(l) 760 | count = len(l) 761 | self.stream.write(HproseTags.TagList) 762 | if count > 0: self.stream.write(str(count).encode('utf-8')) 763 | self.stream.write(HproseTags.TagOpenbrace) 764 | for i in range(count): self.serialize(l[i]) 765 | self.stream.write(HproseTags.TagClosebrace) 766 | def writeListWithRef(self, l): 767 | if not self.refer.write(l): self.writeList(l) 768 | def writeView(self, view): 769 | self.refer.set(view) 770 | count = len(view) 771 | self.stream.write(HproseTags.TagList) 772 | if count > 0: self.stream.write(str(count).encode('utf-8')) 773 | self.stream.write(HproseTags.TagOpenbrace) 774 | for v in view: self.serialize(v) 775 | self.stream.write(HproseTags.TagClosebrace) 776 | def writeViewWithRef(self, view): 777 | if not self.refer.write(view): self.writeView(view) 778 | def writeMap(self, m): 779 | self.refer.set(m) 780 | count = len(m) 781 | self.stream.write(HproseTags.TagMap) 782 | if count > 0: self.stream.write(str(count).encode('utf-8')) 783 | self.stream.write(HproseTags.TagOpenbrace) 784 | for key in m: 785 | self.serialize(key) 786 | self.serialize(m[key]) 787 | self.stream.write(HproseTags.TagClosebrace) 788 | def writeMapWithRef(self, m): 789 | if not self.refer.write(m): self.writeMap(m) 790 | def writeObject(self, obj): 791 | classname = HproseClassManager.getClassAlias(obj.__class__) 792 | if classname in self.classref: 793 | index = self.classref[classname] 794 | fields = self.fieldsref[index] 795 | else: 796 | data = vars(obj) 797 | fields = tuple(data.keys()) 798 | index = self.__writeClass(classname, fields) 799 | self.stream.write(HproseTags.TagObject) 800 | self.stream.write(str(index).encode('utf-8')) 801 | self.stream.write(HproseTags.TagOpenbrace) 802 | self.refer.set(obj) 803 | data = vars(obj) 804 | count = len(fields) 805 | for i in range(count): 806 | self.serialize(data[fields[i]]) 807 | self.stream.write(HproseTags.TagClosebrace) 808 | def writeObjectWithRef(self, obj): 809 | if not self.refer.write(obj): self.writeObject(obj) 810 | def __writeClass(self, classname, fields): 811 | count = len(fields) 812 | self.stream.write(HproseTags.TagClass) 813 | self.stream.write(str(len(classname)).encode('utf-8')) 814 | self.stream.write(HproseTags.TagQuote) 815 | self.stream.write(classname.encode('utf-8')) 816 | self.stream.write(HproseTags.TagQuote) 817 | if count > 0: self.stream.write(str(count).encode('utf-8')) 818 | self.stream.write(HproseTags.TagOpenbrace) 819 | for i in range(count): 820 | field = fields[i] 821 | self.writeString(field) 822 | self.stream.write(HproseTags.TagClosebrace) 823 | index = len(self.fieldsref) 824 | self.fieldsref.append(fields) 825 | self.classref[classname] = index 826 | return index 827 | def reset(self): 828 | self.classref.clear() 829 | del self.fieldsref[:] 830 | self.refer.reset() 831 | 832 | class HproseFormatter: 833 | def serialize(v, simple = False): 834 | stream = BytesIO() 835 | writer = HproseWriter(stream, simple) 836 | writer.serialize(v) 837 | return stream.getvalue() 838 | serialize = staticmethod(serialize) 839 | 840 | def unserialize(s, simple = False): 841 | stream = BytesIO(s) 842 | reader = HproseReader(stream, simple) 843 | return reader.unserialize() 844 | unserialize = staticmethod(unserialize) 845 | -------------------------------------------------------------------------------- /python2/hprose/io.py: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # # 3 | # hprose # 4 | # # 5 | # Official WebSite: http://www.hprose.com/ # 6 | # http://www.hprose.org/ # 7 | # # 8 | ############################################################ 9 | 10 | ############################################################ 11 | # # 12 | # hprose/io.py # 13 | # # 14 | # hprose io for python 2.3+ # 15 | # # 16 | # LastModified: Mar 8, 2015 # 17 | # Author: Ma Bingyao # 18 | # # 19 | ############################################################ 20 | 21 | from cStringIO import StringIO 22 | import datetime 23 | from fpconst import NaN, PosInf, NegInf, isInf, isNaN, isPosInf 24 | from inspect import isclass 25 | from sys import modules 26 | from threading import RLock 27 | from uuid import UUID 28 | from hprose.common import HproseException 29 | import decimal 30 | 31 | Unicode = False 32 | 33 | ZERO = datetime.timedelta(0) 34 | 35 | class UTC(datetime.tzinfo): 36 | def utcoffset(self, dt): 37 | return ZERO 38 | def tzname(self, dt): 39 | return "UTC" 40 | def dst(self, dt): 41 | return ZERO 42 | utc = UTC() 43 | 44 | class HproseTags: 45 | # Serialize Tags # 46 | TagInteger = 'i' 47 | TagLong = 'l' 48 | TagDouble = 'd' 49 | TagNull = 'n' 50 | TagEmpty = 'e' 51 | TagTrue = 't' 52 | TagFalse = 'f' 53 | TagNaN = 'N' 54 | TagInfinity = 'I' 55 | TagDate = 'D' 56 | TagTime = 'T' 57 | TagUTC = 'Z' 58 | TagBytes = 'b' 59 | TagUTF8Char = 'u' 60 | TagString = 's' 61 | TagGuid = 'g' 62 | TagList = 'a' 63 | TagMap = 'm' 64 | TagClass = 'c' 65 | TagObject = 'o' 66 | TagRef = 'r' 67 | # Serialize Marks # 68 | TagPos = '+' 69 | TagNeg = '-' 70 | TagSemicolon = ';' 71 | TagOpenbrace = '{' 72 | TagClosebrace = '}' 73 | TagQuote = '"' 74 | TagPoint = '.' 75 | # Protocol Tags # 76 | TagFunctions = 'F' 77 | TagCall = 'C' 78 | TagResult = 'R' 79 | TagArgument = 'A' 80 | TagError = 'E' 81 | TagEnd = 'z' 82 | 83 | _classCache1 = {} 84 | _classCache2 = {} 85 | _classCacheLock = RLock() 86 | 87 | def _get_class(name): 88 | name = name.split('.') 89 | if len(name) == 1: 90 | return getattr(modules['__main__'], name[0], None) 91 | clsname = name.pop() 92 | modname = '.'.join(name) 93 | if modname in modules: 94 | return getattr(modules[modname], clsname, None) 95 | return None 96 | 97 | def _get_class2(name, ps, i, c): 98 | if i < len(ps): 99 | p = ps[i] 100 | name = name[:p] + c + name[p + 1:] 101 | cls = _get_class2(name, ps, i + 1, '.') 102 | if (i + 1 < len(ps)) and (cls == None): 103 | cls = _get_class2(name, ps, i + 1, '_') 104 | return cls 105 | return _get_class(name) 106 | 107 | def _get_class_by_alias(name): 108 | cls = getattr(modules['__main__'], name, None) 109 | if not isclass(cls): 110 | ps = [] 111 | p = name.find('_') 112 | while p > -1: 113 | ps.append(p) 114 | p = name.find('_', p + 1) 115 | cls = _get_class2(name, ps, 0, '.') 116 | if cls == None: 117 | cls = _get_class2(name, ps, 0, '_') 118 | if cls == None: 119 | cls = type(name, (), {}) 120 | cls.__module__ = '__main__' 121 | setattr(modules['__main__'], name, cls) 122 | return cls 123 | 124 | class HproseClassManager: 125 | def register(_class, alias): 126 | _classCacheLock.acquire() 127 | try: 128 | _classCache1[_class] = alias 129 | _classCache2[alias] = _class 130 | finally: 131 | _classCacheLock.release() 132 | register = staticmethod(register) 133 | 134 | def getClass(alias): 135 | if alias in _classCache2: 136 | return _classCache2[alias] 137 | _class = _get_class_by_alias(alias) 138 | HproseClassManager.register(_class, alias) 139 | return _class 140 | getClass = staticmethod(getClass) 141 | 142 | def getClassAlias(_class): 143 | if _class in _classCache1: 144 | return _classCache1[_class] 145 | alias = [] 146 | if _class.__module__ != '__main__': 147 | alias.extend(_class.__module__.split('.')) 148 | alias.append(_class.__name__) 149 | alias = '_'.join(alias) 150 | HproseClassManager.register(_class, alias) 151 | return alias 152 | getClassAlias = staticmethod(getClassAlias) 153 | 154 | def _readuntil(stream, char): 155 | a = [] 156 | while True: 157 | c = stream.read(1) 158 | if (c == char) or (c == ''): break 159 | a.append(c) 160 | return ''.join(a) 161 | 162 | def _readint(stream, char): 163 | s = _readuntil(stream, char) 164 | if s == '': return 0 165 | return int(s, 10) 166 | 167 | class HproseRawReader(object): 168 | def __init__(self, stream): 169 | self.stream = stream 170 | def unexpectedTag(self, tag, expectTags = None): 171 | if tag == '': 172 | raise HproseException, "No byte found in stream" 173 | elif expectTags == None: 174 | raise HproseException, "Unexpected serialize tag '%s' in stream" % tag 175 | else: 176 | raise HproseException, "Tag '%s' expected, but '%s' found in stream" % (expectTags, tag) 177 | def readRaw(self, ostream = None, tag = None): 178 | if ostream == None: 179 | ostream = StringIO() 180 | if tag == None: 181 | tag = self.stream.read(1) 182 | ostream.write(tag) 183 | if ('0' <= tag <= '9' or 184 | tag == HproseTags.TagNull or 185 | tag == HproseTags.TagEmpty or 186 | tag == HproseTags.TagTrue or 187 | tag == HproseTags.TagFalse or 188 | tag == HproseTags.TagNaN): 189 | pass 190 | elif tag == HproseTags.TagInfinity: 191 | ostream.write(self.stream.read(1)) 192 | elif (tag == HproseTags.TagInteger or 193 | tag == HproseTags.TagLong or 194 | tag == HproseTags.TagDouble or 195 | tag == HproseTags.TagRef): 196 | self.__readNumberRaw(ostream) 197 | elif (tag == HproseTags.TagDate or 198 | tag == HproseTags.TagTime): 199 | self.__readDateTimeRaw(ostream) 200 | elif tag == HproseTags.TagUTF8Char: 201 | self.__readUTF8CharRaw(ostream) 202 | elif tag == HproseTags.TagBytes: 203 | self.__readBytesRaw(ostream) 204 | elif tag == HproseTags.TagString: 205 | self.__readStringRaw(ostream) 206 | elif tag == HproseTags.TagGuid: 207 | self.__readGuidRaw(ostream) 208 | elif (tag == HproseTags.TagList or 209 | tag == HproseTags.TagMap or 210 | tag == HproseTags.TagObject): 211 | self.__readComplexRaw(ostream) 212 | elif tag == HproseTags.TagClass: 213 | self.__readComplexRaw(ostream) 214 | self.readRaw(ostream) 215 | elif tag == HproseTags.TagError: 216 | self.readRaw(ostream) 217 | else: 218 | self.unexpectedTag(tag) 219 | return ostream 220 | def __readNumberRaw(self, ostream): 221 | ostream.write(_readuntil(self.stream, HproseTags.TagSemicolon)) 222 | ostream.write(HproseTags.TagSemicolon) 223 | def __readDateTimeRaw(self, ostream): 224 | s = [] 225 | while True: 226 | c = self.stream.read(1) 227 | s.append(c) 228 | if (c == HproseTags.TagSemicolon or 229 | c == HproseTags.TagUTC): break 230 | ostream.write(''.join(s)) 231 | def __readUTF8CharRaw(self, ostream): 232 | s = [] 233 | c = self.stream.read(1) 234 | s.append(c) 235 | a = ord(c) 236 | if (a & 0xE0) == 0xC0: 237 | s.append(self.stream.read(1)) 238 | elif (a & 0xF0) == 0xE0: 239 | s.append(self.stream.read(2)) 240 | elif a > 0x7F: 241 | raise HproseException, 'Bad utf-8 encoding' 242 | ostream.write(''.join(s)) 243 | def __readBytesRaw(self, ostream): 244 | l = _readuntil(self.stream, HproseTags.TagQuote) 245 | ostream.write(l) 246 | ostream.write(HproseTags.TagQuote) 247 | if l == '': 248 | l = 0 249 | else: 250 | l = int(l, 10) 251 | ostream.write(self.stream.read(l + 1)) 252 | def __readStringRaw(self, ostream): 253 | l = _readuntil(self.stream, HproseTags.TagQuote) 254 | ostream.write(l) 255 | ostream.write(HproseTags.TagQuote) 256 | if l == '': 257 | l = 0 258 | else: 259 | l = int(l, 10) 260 | s = [] 261 | i = 0 262 | while i < l: 263 | c = self.stream.read(1) 264 | s.append(c) 265 | a = ord(c) 266 | if (a & 0xE0) == 0xC0: 267 | s.append(self.stream.read(1)) 268 | elif (a & 0xF0) == 0xE0: 269 | s.append(self.stream.read(2)) 270 | elif (a & 0xF8) == 0xF0: 271 | s.append(self.stream.read(3)) 272 | i += 1 273 | i += 1 274 | s.append(self.stream.read(1)) 275 | ostream.write(''.join(s)) 276 | def __readGuidRaw(self, ostream): 277 | ostream.write(self.stream.read(38)) 278 | def __readComplexRaw(self, ostream): 279 | ostream.write(_readuntil(self.stream, HproseTags.TagOpenbrace)) 280 | ostream.write(HproseTags.TagOpenbrace) 281 | tag = self.stream.read(1) 282 | while tag != HproseTags.TagClosebrace: 283 | self.readRaw(ostream, tag) 284 | tag = self.stream.read(1) 285 | ostream.write(tag) 286 | 287 | class FakeReaderRefer: 288 | def set(self, val): 289 | pass 290 | def read(self, index): 291 | raise HproseException, "Unexpected serialize tag '%s' in stream" % HproseTags.TagRef 292 | def reset(self): 293 | pass 294 | 295 | class RealReaderRefer: 296 | def __init__(self): 297 | self.ref = [] 298 | def set(self, val): 299 | self.ref.append(val) 300 | def read(self, index): 301 | return self.ref[index] 302 | def reset(self): 303 | del self.ref[:] 304 | 305 | class HproseReader(HproseRawReader): 306 | def __init__(self, stream, simple = False): 307 | super(HproseReader, self).__init__(stream) 308 | self.refer = (simple and [FakeReaderRefer()] or [RealReaderRefer()])[0] 309 | self.classref = [] 310 | def unserialize(self): 311 | tag = self.stream.read(1) 312 | if '0' <= tag <= '9': 313 | return int(tag, 10) 314 | if tag == HproseTags.TagInteger: 315 | return self.__readIntegerWithoutTag() 316 | if tag == HproseTags.TagLong: 317 | return self.__readLongWithoutTag() 318 | if tag == HproseTags.TagDouble: 319 | return self.__readDoubleWithoutTag() 320 | if tag == HproseTags.TagNull: 321 | return None 322 | if tag == HproseTags.TagEmpty: 323 | return (Unicode and [u''] or [''])[0] 324 | if tag == HproseTags.TagTrue: 325 | return True 326 | if tag == HproseTags.TagFalse: 327 | return False 328 | if tag == HproseTags.TagNaN: 329 | return NaN 330 | if tag == HproseTags.TagInfinity: 331 | return self.__readInfinityWithoutTag() 332 | if tag == HproseTags.TagDate: 333 | return self.readDateWithoutTag() 334 | if tag == HproseTags.TagTime: 335 | return self.readTimeWithoutTag() 336 | if tag == HproseTags.TagBytes: 337 | return self.readBytesWithoutTag() 338 | if tag == HproseTags.TagUTF8Char: 339 | return self.__readUTF8CharWithoutTag() 340 | if tag == HproseTags.TagString: 341 | return self.readStringWithoutTag() 342 | if tag == HproseTags.TagGuid: 343 | return self.readGuidWithoutTag() 344 | if tag == HproseTags.TagList: 345 | return self.readListWithoutTag() 346 | if tag == HproseTags.TagMap: 347 | return self.readMapWithoutTag() 348 | if tag == HproseTags.TagClass: 349 | self.__readClass() 350 | return self.readObject() 351 | if tag == HproseTags.TagObject: 352 | return self.readObjectWithoutTag() 353 | if tag == HproseTags.TagRef: 354 | return self.__readRef() 355 | if tag == HproseTags.TagError: 356 | raise HproseException, self.readString() 357 | self.unexpectedTag(tag) 358 | def checkTag(self, expectTag): 359 | tag = self.stream.read(1) 360 | if tag != expectTag: 361 | self.unexpectedTag(tag, expectTag) 362 | def checkTags(self, expectTags): 363 | tag = self.stream.read(1) 364 | if tag not in expectTags: 365 | self.unexpectedTag(tag, ''.join(expectTags)) 366 | return tag 367 | def __readIntegerWithoutTag(self): 368 | return int(_readuntil(self.stream, HproseTags.TagSemicolon), 10) 369 | def readInteger(self): 370 | tag = self.stream.read(1) 371 | if '0' <= tag <= '9': 372 | return int(tag, 10) 373 | if tag == HproseTags.TagInteger: 374 | return self.__readIntegerWithoutTag() 375 | self.unexpectedTag(tag) 376 | def __readLongWithoutTag(self): 377 | return long(_readuntil(self.stream, HproseTags.TagSemicolon)) 378 | def readLong(self): 379 | tag = self.stream.read(1) 380 | if '0' <= tag <= '9': 381 | return long(tag) 382 | if (tag == HproseTags.TagInteger or 383 | tag == HproseTags.TagLong): 384 | return self.__readLongWithoutTag() 385 | self.unexpectedTag(tag) 386 | def __readDoubleWithoutTag(self): 387 | return float(_readuntil(self.stream, HproseTags.TagSemicolon)) 388 | def readDouble(self): 389 | tag = self.stream.read(1) 390 | if '0' <= tag <= '9': 391 | return float(tag) 392 | if (tag == HproseTags.TagInteger or 393 | tag == HproseTags.TagLong or 394 | tag == HproseTags.TagDouble): 395 | return self.__readDoubleWithoutTag() 396 | if tag == HproseTags.TagNaN: 397 | return NaN 398 | if tag == HproseTags.TagInfinity: 399 | return self.__readInfinityWithoutTag() 400 | self.unexpectedTag(tag) 401 | def __readInfinityWithoutTag(self): 402 | if self.stream.read(1) == HproseTags.TagNeg: 403 | return NegInf 404 | else: 405 | return PosInf 406 | def readBoolean(self): 407 | tag = self.checkTags((HproseTags.TagTrue, HproseTags.TagFalse)) 408 | return tag == HproseTags.TagTrue 409 | def readDateWithoutTag(self): 410 | year = int(self.stream.read(4), 10) 411 | month = int(self.stream.read(2), 10) 412 | day = int(self.stream.read(2), 10) 413 | tag = self.stream.read(1) 414 | if tag == HproseTags.TagTime: 415 | hour = int(self.stream.read(2), 10) 416 | minute = int(self.stream.read(2), 10) 417 | second = int(self.stream.read(2), 10) 418 | (tag, microsecond) = self.__readMicrosecond() 419 | if tag == HproseTags.TagUTC: 420 | d = datetime.datetime(year, month, day, hour, minute, second, microsecond, utc) 421 | else: 422 | d = datetime.datetime(year, month, day, hour, minute, second, microsecond) 423 | elif tag == HproseTags.TagUTC: 424 | d = datetime.datetime(year, month, day, 0, 0, 0, 0, utc) 425 | else: 426 | d = datetime.date(year, month, day) 427 | self.refer.set(d) 428 | return d 429 | def readDate(self): 430 | tag = self.stream.read(1) 431 | if tag == HproseTags.TagNull: return None 432 | if tag == HproseTags.TagRef: return self.__readRef() 433 | if tag == HproseTags.TagDate: return self.readDateWithoutTag() 434 | self.unexpectedTag(tag) 435 | def readTimeWithoutTag(self): 436 | hour = int(self.stream.read(2), 10) 437 | minute = int(self.stream.read(2), 10) 438 | second = int(self.stream.read(2), 10) 439 | (tag, microsecond) = self.__readMicrosecond() 440 | if tag == HproseTags.TagUTC: 441 | t = datetime.time(hour, minute, second, microsecond, utc) 442 | else: 443 | t = datetime.time(hour, minute, second, microsecond) 444 | self.refer.set(t) 445 | return t 446 | def readTime(self): 447 | tag = self.stream.read(1) 448 | if tag == HproseTags.TagNull: return None 449 | if tag == HproseTags.TagRef: return self.__readRef() 450 | if tag == HproseTags.TagTime: return self.readTimeWithoutTag() 451 | self.unexpectedTag(tag) 452 | def readBytesWithoutTag(self): 453 | b = self.stream.read(_readint(self.stream, HproseTags.TagQuote)) 454 | self.stream.read(1) 455 | self.refer.set(b) 456 | return b 457 | def readBytes(self): 458 | tag = self.stream.read(1) 459 | if tag == HproseTags.TagNull: return None 460 | if tag == HproseTags.TagEmpty: return '' 461 | if tag == HproseTags.TagRef: return self.__readRef() 462 | if tag == HproseTags.TagBytes: return self.readBytesWithoutTag() 463 | self.unexpectedTag(tag) 464 | def __readUTF8CharWithoutTag(self): 465 | s = [] 466 | c = self.stream.read(1) 467 | s.append(c) 468 | a = ord(c) 469 | if (a & 0xE0) == 0xC0: 470 | s.append(self.stream.read(1)) 471 | elif (a & 0xF0) == 0xE0: 472 | s.append(self.stream.read(2)) 473 | elif a > 0x7F: 474 | raise HproseException, 'Bad utf-8 encoding' 475 | s = ''.join(s) 476 | if Unicode: 477 | s = unicode(s, 'utf-8') 478 | return s 479 | def __readString(self): 480 | l = _readint(self.stream, HproseTags.TagQuote) 481 | s = [] 482 | i = 0 483 | while i < l: 484 | c = self.stream.read(1) 485 | s.append(c) 486 | a = ord(c) 487 | if (a & 0xE0) == 0xC0: 488 | s.append(self.stream.read(1)) 489 | elif (a & 0xF0) == 0xE0: 490 | s.append(self.stream.read(2)) 491 | elif (a & 0xF8) == 0xF0: 492 | s.append(self.stream.read(3)) 493 | i += 1 494 | i += 1 495 | self.stream.read(1) 496 | s = ''.join(s) 497 | if Unicode: 498 | s = unicode(s, 'utf-8') 499 | return s 500 | def readStringWithoutTag(self): 501 | s = self.__readString() 502 | self.refer.set(s) 503 | return s 504 | def readString(self): 505 | tag = self.stream.read(1) 506 | if tag == HproseTags.TagNull: return None 507 | if tag == HproseTags.TagEmpty: return (Unicode and [u''] or [''])[0] 508 | if tag == HproseTags.TagUTF8Char: return self.__readUTF8CharWithoutTag() 509 | if tag == HproseTags.TagRef: return self.__readRef() 510 | if tag == HproseTags.TagString: return self.readStringWithoutTag() 511 | self.unexpectedTag(tag) 512 | def readGuidWithoutTag(self): 513 | u = UUID(self.stream.read(38)) 514 | self.refer.set(u) 515 | return u 516 | def readGuid(self): 517 | tag = self.stream.read(1) 518 | if tag == HproseTags.TagNull: return None 519 | if tag == HproseTags.TagRef: return self.__readRef() 520 | if tag == HproseTags.TagGuid: return self.readGuidWithoutTag() 521 | self.unexpectedTag(tag) 522 | def readListWithoutTag(self): 523 | l = [] 524 | self.refer.set(l) 525 | c = _readint(self.stream, HproseTags.TagOpenbrace) 526 | for _ in xrange(c): l.append(self.unserialize()) 527 | self.stream.read(1) 528 | return l 529 | def readList(self): 530 | tag = self.stream.read(1) 531 | if tag == HproseTags.TagNull: return None 532 | if tag == HproseTags.TagRef: return self.__readRef() 533 | if tag == HproseTags.TagList: return self.readListWithoutTag() 534 | self.unexpectedTag(tag) 535 | def readMapWithoutTag(self): 536 | m = {} 537 | self.refer.set(m) 538 | c = _readint(self.stream, HproseTags.TagOpenbrace) 539 | for _ in xrange(c): 540 | k = self.unserialize() 541 | v = self.unserialize() 542 | m[k] = v 543 | self.stream.read(1) 544 | return m 545 | def readMap(self): 546 | tag = self.stream.read(1) 547 | if tag == HproseTags.TagNull: return None 548 | if tag == HproseTags.TagRef: return self.__readRef() 549 | if tag == HproseTags.TagMap: return self.readMapWithoutTag() 550 | self.unexpectedTag(tag) 551 | def readObjectWithoutTag(self): 552 | (cls, count, fields) = self.classref[_readint(self.stream, HproseTags.TagOpenbrace)] 553 | obj = cls() 554 | self.refer.set(obj) 555 | for i in xrange(count): setattr(obj, fields[i], self.unserialize()) 556 | self.stream.read(1) 557 | return obj 558 | def readObject(self): 559 | tag = self.stream.read(1) 560 | if tag == HproseTags.TagNull: return None 561 | if tag == HproseTags.TagRef: return self.__readRef() 562 | if tag == HproseTags.TagObject: return self.readObjectWithoutTag() 563 | if tag == HproseTags.TagClass: 564 | self.__readClass() 565 | return self.readObject() 566 | self.unexpectedTag(tag) 567 | def __readClass(self): 568 | classname = self.__readString() 569 | count = _readint(self.stream, HproseTags.TagOpenbrace) 570 | fields = [self.readString() for _ in xrange(count)] 571 | self.stream.read(1) 572 | cls = HproseClassManager.getClass(classname) 573 | self.classref.append((cls, count, fields)) 574 | def __readRef(self): 575 | return self.refer.read(_readint(self.stream, HproseTags.TagSemicolon)) 576 | def __readMicrosecond(self): 577 | microsecond = 0 578 | tag = self.stream.read(1) 579 | if tag == HproseTags.TagPoint: 580 | microsecond = int(self.stream.read(3), 10) * 1000 581 | tag = self.stream.read(1) 582 | if '0' <= tag <= '9': 583 | microsecond = microsecond + int(tag + self.stream.read(2), 10) 584 | tag = self.stream.read(1) 585 | if '0' <= tag <= '9': 586 | self.stream.read(2) 587 | tag = self.stream.read(1) 588 | return (tag, microsecond) 589 | def reset(self): 590 | del self.classref[:] 591 | self.refer.reset() 592 | 593 | class FakeWriterRefer: 594 | def set(self, val): 595 | pass 596 | def write(self, val): 597 | return False 598 | def reset(self): 599 | pass 600 | 601 | class RealWriterRefer: 602 | def __init__(self, stream): 603 | self.stream = stream 604 | self.ref = {} 605 | self.refcount = 0 606 | def set(self, val): 607 | if isinstance(val, str) or isinstance(val, unicode): 608 | self.ref[val] = self.refcount 609 | else: 610 | self.ref[id(val)] = self.refcount 611 | self.refcount += 1 612 | def write(self, val): 613 | if not (isinstance(val, str) or isinstance(val, unicode)): 614 | val = id(val) 615 | if (val in self.ref): 616 | self.stream.write('%c%d%c' % (HproseTags.TagRef, 617 | self.ref[val], 618 | HproseTags.TagSemicolon)) 619 | return True 620 | return False 621 | def reset(self): 622 | self.ref.clear() 623 | self.refcount = 0 624 | 625 | class HproseWriter(object): 626 | def __init__(self, stream, simple = False): 627 | self.stream = stream 628 | self.classref = {} 629 | self.fieldsref = [] 630 | self.refer = (simple and [FakeWriterRefer()] or [RealWriterRefer(stream)])[0] 631 | def serialize(self, v): 632 | if v == None: self.writeNull() 633 | elif isinstance(v, bool): self.writeBoolean(v) 634 | elif isinstance(v, int): self.writeInteger(v) 635 | elif isinstance(v, float): self.writeDouble(v) 636 | elif isinstance(v, decimal.Decimal): self.writeDouble(v) 637 | elif isinstance(v, long): self.writeLong(v) 638 | elif isinstance(v, str): 639 | if v == '': 640 | self.writeEmpty() 641 | elif Unicode: 642 | self.writeBytesWithRef(v) 643 | else: 644 | try: 645 | self.writeStringWithRef(unicode(v, 'utf-8')) 646 | except ValueError: 647 | self.writeBytesWithRef(v) 648 | elif isinstance(v, unicode): 649 | if v == u'': 650 | self.writeEmpty() 651 | elif len(v) == 1: 652 | self.writeUTF8Char(v) 653 | else: 654 | self.writeStringWithRef(v) 655 | elif isinstance(v, UUID): self.writeGuidWithRef(v) 656 | elif isinstance(v, (list, tuple)): self.writeListWithRef(v) 657 | elif isinstance(v, dict): self.writeMapWithRef(v) 658 | elif isinstance(v, (datetime.datetime, datetime.date)): self.writeDateWithRef(v) 659 | elif isinstance(v, datetime.time): self.writeTimeWithRef(v) 660 | elif isinstance(v, object): self.writeObjectWithRef(v) 661 | else: raise HproseException, 'Not support to serialize this data' 662 | def writeInteger(self, i): 663 | if 0 <= i <= 9: 664 | self.stream.write('%d' % (i,)) 665 | else: 666 | self.stream.write('%c%d%c' % (HproseTags.TagInteger, 667 | i, 668 | HproseTags.TagSemicolon)) 669 | def writeLong(self, l): 670 | if 0 <= l <= 9: 671 | self.stream.write('%d' % (l,)) 672 | else: 673 | self.stream.write('%c%d%c' % (HproseTags.TagLong, 674 | l, 675 | HproseTags.TagSemicolon)) 676 | def writeDouble(self, d): 677 | if isNaN(d): self.writeNaN() 678 | elif isInf(d): self.writeInfinity(isPosInf(d)) 679 | else: self.stream.write('%c%s%c' % (HproseTags.TagDouble, 680 | d, 681 | HproseTags.TagSemicolon)) 682 | def writeNaN(self): 683 | self.stream.write(HproseTags.TagNaN) 684 | def writeInfinity(self, positive = True): 685 | self.stream.write(HproseTags.TagInfinity) 686 | if positive: 687 | self.stream.write(HproseTags.TagPos) 688 | else: 689 | self.stream.write(HproseTags.TagNeg) 690 | def writeNull(self): 691 | self.stream.write(HproseTags.TagNull) 692 | def writeEmpty(self): 693 | self.stream.write(HproseTags.TagEmpty) 694 | def writeBoolean(self, b): 695 | if b: 696 | self.stream.write(HproseTags.TagTrue) 697 | else: 698 | self.stream.write(HproseTags.TagFalse) 699 | def writeDate(self, date): 700 | self.refer.set(date) 701 | if isinstance(date, datetime.datetime): 702 | if date.utcoffset() != ZERO and date.utcoffset() != None: 703 | date = date.astimezone(utc) 704 | if date.hour == 0 and date.minute == 0 and date.second == 0 and date.microsecond == 0: 705 | fmt = '%c%s' % (HproseTags.TagDate, '%Y%m%d') 706 | elif date.year == 1970 and date.month == 1 and date.day == 1: 707 | fmt = '%c%s' % (HproseTags.TagTime, '%H%M%S') 708 | else: 709 | fmt = '%c%s%c%s' % (HproseTags.TagDate, '%Y%m%d', HproseTags.TagTime, '%H%M%S') 710 | if date.microsecond > 0: 711 | fmt = '%s%c%s' % (fmt, HproseTags.TagPoint, '%f') 712 | if date.utcoffset() == ZERO: 713 | fmt = '%s%c' % (fmt, HproseTags.TagUTC) 714 | else: 715 | fmt = '%s%c' % (fmt, HproseTags.TagSemicolon) 716 | else: 717 | fmt = '%c%s%c' % (HproseTags.TagDate, '%Y%m%d', HproseTags.TagSemicolon) 718 | self.stream.write(date.strftime(fmt)) 719 | def writeDateWithRef(self, date): 720 | if not self.refer.write(date): self.writeDate(date) 721 | def writeTime(self, time): 722 | self.refer.set(time) 723 | fmt = '%c%s' % (HproseTags.TagTime, '%H%M%S') 724 | if time.microsecond > 0: 725 | fmt = '%s%c%s' % (fmt, HproseTags.TagPoint, '%f') 726 | if time.utcoffset() == ZERO: 727 | fmt = '%s%c' % (fmt, HproseTags.TagUTC) 728 | else: 729 | fmt = '%s%c' % (fmt, HproseTags.TagSemicolon) 730 | self.stream.write(time.strftime(fmt)) 731 | def writeTimeWithRef(self, time): 732 | if not self.refer.write(time): self.writeTime(time) 733 | def writeBytes(self, b): 734 | self.refer.set(b) 735 | length = len(b) 736 | if length == 0: 737 | self.stream.write('%c%c%c' % (HproseTags.TagBytes, 738 | HproseTags.TagQuote, 739 | HproseTags.TagQuote)) 740 | else: 741 | self.stream.write('%c%d%c%s%c' % (HproseTags.TagBytes, 742 | length, 743 | HproseTags.TagQuote, 744 | b, 745 | HproseTags.TagQuote)) 746 | def writeBytesWithRef(self, b): 747 | if not self.refer.write(b): self.writeBytes(b) 748 | def writeUTF8Char(self, u): 749 | self.stream.write('%c%s' % (HproseTags.TagUTF8Char, u.encode('utf-8'))) 750 | def writeString(self, s): 751 | self.refer.set(s) 752 | length = len(s) 753 | if length == 0: 754 | self.stream.write('%c%c%c' % (HproseTags.TagString, 755 | HproseTags.TagQuote, 756 | HproseTags.TagQuote)) 757 | else: 758 | self.stream.write('%c%d%c%s%c' % (HproseTags.TagString, 759 | length, 760 | HproseTags.TagQuote, 761 | s.encode('utf-8'), 762 | HproseTags.TagQuote)) 763 | def writeStringWithRef(self, s): 764 | if not self.refer.write(s): self.writeString(s) 765 | def writeGuid(self, guid): 766 | self.refer.set(guid) 767 | self.stream.write(HproseTags.TagGuid) 768 | self.stream.write(HproseTags.TagOpenbrace) 769 | self.stream.write(str(guid)) 770 | self.stream.write(HproseTags.TagClosebrace) 771 | def writeGuidWithRef(self, guid): 772 | if not self.refer.write(guid): self.writeGuid(guid) 773 | def writeList(self, l): 774 | self.refer.set(l) 775 | count = len(l) 776 | if count == 0: 777 | self.stream.write('%c%c' % (HproseTags.TagList, 778 | HproseTags.TagOpenbrace)) 779 | else: 780 | self.stream.write('%c%d%c' % (HproseTags.TagList, 781 | count, 782 | HproseTags.TagOpenbrace)) 783 | for i in xrange(count): self.serialize(l[i]) 784 | self.stream.write(HproseTags.TagClosebrace) 785 | def writeListWithRef(self, l): 786 | if not self.refer.write(l): self.writeList(l) 787 | def writeMap(self, m): 788 | self.refer.set(m) 789 | count = len(m) 790 | if count == 0: 791 | self.stream.write('%c%c' % (HproseTags.TagMap, 792 | HproseTags.TagOpenbrace)) 793 | else: 794 | self.stream.write('%c%d%c' % (HproseTags.TagMap, 795 | count, 796 | HproseTags.TagOpenbrace)) 797 | for key in m: 798 | self.serialize(key) 799 | self.serialize(m[key]) 800 | self.stream.write(HproseTags.TagClosebrace) 801 | def writeMapWithRef(self, m): 802 | if not self.refer.write(m): self.writeMap(m) 803 | def writeObject(self, obj): 804 | classname = HproseClassManager.getClassAlias(obj.__class__) 805 | if classname in self.classref: 806 | index = self.classref[classname] 807 | fields = self.fieldsref[index] 808 | else: 809 | data = vars(obj) 810 | fields = tuple(data.keys()) 811 | index = self.__writeClass(classname, fields) 812 | self.stream.write('%c%d%c' % (HproseTags.TagObject, 813 | index, 814 | HproseTags.TagOpenbrace)) 815 | self.refer.set(obj) 816 | data = vars(obj) 817 | count = len(fields) 818 | for i in xrange(count): 819 | self.serialize(data[fields[i]]) 820 | self.stream.write(HproseTags.TagClosebrace) 821 | def writeObjectWithRef(self, obj): 822 | if not self.refer.write(obj): self.writeObject(obj) 823 | def __writeClass(self, classname, fields): 824 | length = len(unicode(classname, 'utf-8')) 825 | count = len(fields) 826 | if count == 0: 827 | self.stream.write('%c%d%c%s%c%c' % (HproseTags.TagClass, 828 | length, 829 | HproseTags.TagQuote, 830 | classname, 831 | HproseTags.TagQuote, 832 | HproseTags.TagOpenbrace)) 833 | else: 834 | self.stream.write('%c%d%c%s%c%d%c' % (HproseTags.TagClass, 835 | length, 836 | HproseTags.TagQuote, 837 | classname, 838 | HproseTags.TagQuote, 839 | count, 840 | HproseTags.TagOpenbrace)) 841 | for i in xrange(count): 842 | field = unicode(fields[i], 'utf-8') 843 | self.writeString(field) 844 | self.stream.write(HproseTags.TagClosebrace) 845 | index = len(self.fieldsref) 846 | self.fieldsref.append(fields) 847 | self.classref[classname] = index 848 | return index 849 | def reset(self): 850 | self.classref.clear() 851 | del self.fieldsref[:] 852 | self.refer.reset() 853 | 854 | class HproseFormatter: 855 | def serialize(v, simple = False): 856 | stream = StringIO() 857 | writer = HproseWriter(stream, simple) 858 | writer.serialize(v) 859 | return stream.getvalue() 860 | serialize = staticmethod(serialize) 861 | 862 | def unserialize(s, simple = False): 863 | stream = StringIO(s) 864 | reader = HproseReader(stream, simple) 865 | return reader.unserialize() 866 | unserialize = staticmethod(unserialize) 867 | --------------------------------------------------------------------------------