diff --git a/autobahn/wamp/exception.py b/autobahn/wamp/exception.py index 0666862e..e628cb89 100644 --- a/autobahn/wamp/exception.py +++ b/autobahn/wamp/exception.py @@ -271,7 +271,6 @@ class ApplicationError(Error): return self.__unicode__().encode('utf8') -@public @error(ApplicationError.NOT_AUTHORIZED) class NotAuthorized(Exception): """ @@ -279,7 +278,6 @@ class NotAuthorized(Exception): """ -@public @error(ApplicationError.INVALID_URI) class InvalidUri(Exception): """ @@ -287,7 +285,6 @@ class InvalidUri(Exception): """ -@public @error(ApplicationError.INVALID_PAYLOAD) class InvalidPayload(Exception): """ diff --git a/autobahn/wamp/request.py b/autobahn/wamp/request.py index 2d1f51c6..9fe90a6a 100644 --- a/autobahn/wamp/request.py +++ b/autobahn/wamp/request.py @@ -33,11 +33,9 @@ __all__ = ( 'Handler', 'Registration', 'Endpoint', - 'PublishRequest', 'SubscribeRequest', 'UnsubscribeRequest', - 'CallRequest', 'InvocationRequest', 'RegisterRequest', @@ -54,6 +52,14 @@ class Publication(object): __slots__ = ('id', 'was_encrypted') def __init__(self, publication_id, was_encrypted): + """ + + :param publication_id: The publication ID of the published event. + :type publication_id: int + + :param was_encrypted: Flag indicating whether the app payload was encrypted. + :type was_encrypted: bool + """ self.id = publication_id self.was_encrypted = was_encrypted @@ -70,6 +76,18 @@ class Subscription(object): def __init__(self, subscription_id, topic, session, handler): """ + + :param subscription_id: The subscription ID. + :type subscription_id: int + + :param topic: The subscription URI or URI pattern. + :type topic: str + + :param session: The ApplicationSession this subscription is living on. + :type session: instance of ApplicationSession + + :param handler: The user event callback. + :type handler: callable """ self.id = subscription_id self.topic = topic @@ -79,6 +97,7 @@ class Subscription(object): def unsubscribe(self): """ + Unsubscribe this subscription. """ if self.active: return self.session._unsubscribe(self) @@ -101,8 +120,10 @@ class Handler(object): :param fn: The event handler function to be called. :type fn: callable + :param obj: The (optional) object upon which to call the function. :type obj: obj or None + :param details_arg: The keyword argument under which event details should be provided. :type details_arg: str or None """ @@ -119,6 +140,20 @@ class Registration(object): __slots__ = ('id', 'active', 'session', 'procedure', 'endpoint') def __init__(self, session, registration_id, procedure, endpoint): + """ + + :param id: The registration ID. + :type id: int + + :param active: Flag indicating whether this registration is active. + :type active: bool + + :param procedure: The procedure URI or URI pattern. + :type procedure: callable + + :param endpoint: The user callback. + :type endpoint: callable + """ self.id = registration_id self.active = True self.session = session @@ -146,8 +181,10 @@ class Endpoint(object): :param fn: The endpoint procedure to be called. :type fn: callable + :param obj: The (optional) object upon which to call the function. :type obj: obj or None + :param details_arg: The keyword argument under which call details should be provided. :type details_arg: str or None """ @@ -169,6 +206,7 @@ class Request(object): :param request_id: The WAMP request ID. :type request_id: int + :param on_reply: The Deferred/Future to be fired when the request returns. :type on_reply: Deferred/Future """ @@ -184,6 +222,17 @@ class PublishRequest(Request): __slots__ = ('was_encrypted') def __init__(self, request_id, on_reply, was_encrypted): + """ + + :param request_id: The WAMP request ID. + :type request_id: int + + :param on_reply: The Deferred/Future to be fired when the request returns. + :type on_reply: Deferred/Future + + :param was_encrypted: Flag indicating whether the app payload was encrypted. + :type was_encrypted: bool + """ Request.__init__(self, request_id, on_reply) self.was_encrypted = was_encrypted @@ -200,10 +249,13 @@ class SubscribeRequest(Request): :param request_id: The WAMP request ID. :type request_id: int + :param topic: The topic URI being subscribed to. :type topic: unicode + :param on_reply: The Deferred/Future to be fired when the request returns. :type on_reply: Deferred/Future + :param handler: WAMP call options that are in use for this call. :type handler: callable """ @@ -217,7 +269,11 @@ class UnsubscribeRequest(Request): Object representing an outstanding request to unsubscribe a subscription. """ + __slots__ = ('subscription_id',) + def __init__(self, request_id, on_reply, subscription_id): + """ + """ Request.__init__(self, request_id, on_reply) self.subscription_id = subscription_id @@ -234,8 +290,10 @@ class CallRequest(Request): :param request_id: The WAMP request ID. :type request_id: int + :param on_reply: The Deferred/Future to be fired when the request returns. :type on_reply: Deferred/Future + :param options: WAMP call options that are in use for this call. :type options: dict """ @@ -255,7 +313,11 @@ class RegisterRequest(Request): Object representing an outstanding request to register a procedure. """ + __slots__ = ('procedure', 'endpoint',) + def __init__(self, request_id, on_reply, procedure, endpoint): + """ + """ Request.__init__(self, request_id, on_reply) self.procedure = procedure self.endpoint = endpoint @@ -266,6 +328,10 @@ class UnregisterRequest(Request): Object representing an outstanding request to unregister a registration. """ + __slots__ = ('registration_id',) + def __init__(self, request_id, on_reply, registration_id): + """ + """ Request.__init__(self, request_id, on_reply) self.registration_id = registration_id diff --git a/autobahn/wamp/uri.py b/autobahn/wamp/uri.py index b785365d..7d39b62a 100644 --- a/autobahn/wamp/uri.py +++ b/autobahn/wamp/uri.py @@ -136,7 +136,8 @@ class Pattern(object): """ :param uri: The URI or URI pattern, e.g. ``"com.myapp.product..update"``. - :type uri: unicode + :type uri: str + :param target: The target for this pattern: a procedure endpoint (a callable), an event handler (a callable) or an exception (a class). :type target: callable or obj @@ -213,7 +214,7 @@ class Pattern(object): Returns the original URI (pattern) for this pattern. :returns: The URI (pattern), e.g. ``"com.myapp.product..update"``. - :rtype: unicode + :rtype: str """ return self._uri @@ -229,7 +230,7 @@ class Pattern(object): and return extracted args and kwargs. :param uri: The URI to match, e.g. ``"com.myapp.product.123456.update"``. - :type uri: unicode + :type uri: str :returns: A tuple ``(args, kwargs)`` :rtype: tuple diff --git a/autobahn/wamp/websocket.py b/autobahn/wamp/websocket.py index 498c6829..67c9bbeb 100644 --- a/autobahn/wamp/websocket.py +++ b/autobahn/wamp/websocket.py @@ -227,6 +227,7 @@ class WampWebSocketFactory(object): :param factory: A callable that produces instances that implement :class:`autobahn.wamp.interfaces.ITransportHandler` :type factory: callable + :param serializers: A list of WAMP serializers to use (or None for default serializers). Serializers must implement :class:`autobahn.wamp.interfaces.ISerializer`. diff --git a/autobahn/websocket/compress.py b/autobahn/websocket/compress.py index 5a732c10..222cd059 100644 --- a/autobahn/websocket/compress.py +++ b/autobahn/websocket/compress.py @@ -44,22 +44,22 @@ from autobahn.websocket.compress_deflate import \ # this must be a list (not tuple), since we dynamically # extend it .. __all__ = [ - "PerMessageCompressOffer", - "PerMessageCompressOfferAccept", - "PerMessageCompressResponse", - "PerMessageCompressResponseAccept", - "PerMessageCompress", - "PerMessageDeflateOffer", - "PerMessageDeflateOfferAccept", - "PerMessageDeflateResponse", - "PerMessageDeflateResponseAccept", - "PerMessageDeflate", - "PERMESSAGE_COMPRESSION_EXTENSION" + 'PerMessageCompressOffer', + 'PerMessageCompressOfferAccept', + 'PerMessageCompressResponse', + 'PerMessageCompressResponseAccept', + 'PerMessageCompress', + 'PerMessageDeflateOffer', + 'PerMessageDeflateOfferAccept', + 'PerMessageDeflateResponse', + 'PerMessageDeflateResponseAccept', + 'PerMessageDeflate', + 'PERMESSAGE_COMPRESSION_EXTENSION' ] -# class for "permessage-deflate" is always available -# +# map of available compression extensions PERMESSAGE_COMPRESSION_EXTENSION = { + # class for 'permessage-deflate' is always available PerMessageDeflateMixin.EXTENSION_NAME: { 'Offer': PerMessageDeflateOffer, 'OfferAccept': PerMessageDeflateOfferAccept, @@ -70,8 +70,7 @@ PERMESSAGE_COMPRESSION_EXTENSION = { } -# include "permessage-bzip2" classes if bzip2 is available -# +# include 'permessage-bzip2' classes if bzip2 is available try: import bz2 except ImportError: @@ -94,15 +93,14 @@ else: } PERMESSAGE_COMPRESSION_EXTENSION[PerMessageBzip2Mixin.EXTENSION_NAME] = PMCE - __all__.extend(["PerMessageBzip2Offer", - "PerMessageBzip2OfferAccept", - "PerMessageBzip2Response", - "PerMessageBzip2ResponseAccept", - "PerMessageBzip2"]) + __all__.extend(['PerMessageBzip2Offer', + 'PerMessageBzip2OfferAccept', + 'PerMessageBzip2Response', + 'PerMessageBzip2ResponseAccept', + 'PerMessageBzip2']) -# include "permessage-snappy" classes if Snappy is available -# +# include 'permessage-snappy' classes if Snappy is available try: # noinspection PyPackageRequirements import snappy @@ -126,8 +124,8 @@ else: } PERMESSAGE_COMPRESSION_EXTENSION[PerMessageSnappyMixin.EXTENSION_NAME] = PMCE - __all__.extend(["PerMessageSnappyOffer", - "PerMessageSnappyOfferAccept", - "PerMessageSnappyResponse", - "PerMessageSnappyResponseAccept", - "PerMessageSnappy"]) + __all__.extend(['PerMessageSnappyOffer', + 'PerMessageSnappyOfferAccept', + 'PerMessageSnappyResponse', + 'PerMessageSnappyResponseAccept', + 'PerMessageSnappy']) diff --git a/autobahn/websocket/compress_bzip2.py b/autobahn/websocket/compress_bzip2.py index 5b759235..63fe271f 100644 --- a/autobahn/websocket/compress_bzip2.py +++ b/autobahn/websocket/compress_bzip2.py @@ -51,13 +51,13 @@ class PerMessageBzip2Mixin(object): EXTENSION_NAME = "permessage-bzip2" """ - Name of this WebSocket extension. - """ + Name of this WebSocket extension. + """ COMPRESS_LEVEL_PERMISSIBLE_VALUES = [1, 2, 3, 4, 5, 6, 7, 8, 9] """ - Permissible value for compression level parameter. - """ + Permissible value for compression level parameter. + """ class PerMessageBzip2Offer(PerMessageCompressOffer, PerMessageBzip2Mixin): @@ -77,13 +77,10 @@ class PerMessageBzip2Offer(PerMessageCompressOffer, PerMessageBzip2Mixin): :returns: object -- A new instance of :class:`autobahn.compress.PerMessageBzip2Offer`. """ # extension parameter defaults - ## - acceptMaxCompressLevel = False - requestMaxCompressLevel = 0 + accept_max_compress_level = False + request_max_compress_level = 0 - ## # verify/parse client ("client-to-server direction") parameters of permessage-bzip2 offer - ## for p in params: if len(params[p]) > 1: @@ -96,7 +93,7 @@ class PerMessageBzip2Offer(PerMessageCompressOffer, PerMessageBzip2Mixin): if val is not True: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - acceptMaxCompressLevel = True + accept_max_compress_level = True elif p == 'server_max_compress_level': try: @@ -106,66 +103,69 @@ class PerMessageBzip2Offer(PerMessageCompressOffer, PerMessageBzip2Mixin): if val not in PerMessageBzip2Mixin.COMPRESS_LEVEL_PERMISSIBLE_VALUES: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - requestMaxCompressLevel = val + request_max_compress_level = val else: raise Exception("illegal extension parameter '%s' for extension '%s'" % (p, cls.EXTENSION_NAME)) - offer = cls(acceptMaxCompressLevel, - requestMaxCompressLevel) + offer = cls(accept_max_compress_level, + request_max_compress_level) return offer def __init__(self, - acceptMaxCompressLevel=True, - requestMaxCompressLevel=0): + accept_max_compress_level=True, + request_max_compress_level=0): """ Constructor. - :param acceptMaxCompressLevel: Iff true, client accepts "maximum compression level" parameter. - :type acceptMaxCompressLevel: bool - :param requestMaxCompressLevel: Iff non-zero, client requests given "maximum compression level" - must be 1-9. - :type requestMaxCompressLevel: int + :param accept_max_compress_level: Iff true, client accepts "maximum compression level" parameter. + :type accept_max_compress_level: bool + :param request_max_compress_level: Iff non-zero, client requests given "maximum compression level" - must be 1-9. + :type request_max_compress_level: int """ - if type(acceptMaxCompressLevel) != bool: - raise Exception("invalid type %s for acceptMaxCompressLevel" % type(acceptMaxCompressLevel)) + if type(accept_max_compress_level) != bool: + raise Exception("invalid type %s for accept_max_compress_level" % type(accept_max_compress_level)) - self.acceptMaxCompressLevel = acceptMaxCompressLevel + self.accept_max_compress_level = accept_max_compress_level - if requestMaxCompressLevel != 0 and requestMaxCompressLevel not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for requestMaxCompressLevel - permissible values %s" % (requestMaxCompressLevel, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) + if request_max_compress_level != 0 and request_max_compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for request_max_compress_level - permissible values %s" % (request_max_compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) - self.requestMaxCompressLevel = requestMaxCompressLevel + self.request_max_compress_level = request_max_compress_level - def getExtensionString(self): + def get_extension_string(self): """ Returns the WebSocket extension configuration string as sent to the server. - :returns: str -- PMCE configuration string. + :returns: PMCE configuration string. + :rtype: str """ - pmceString = self.EXTENSION_NAME - if self.acceptMaxCompressLevel: - pmceString += "; client_max_compress_level" - if self.requestMaxCompressLevel != 0: - pmceString += "; server_max_compress_level=%d" % self.requestMaxCompressLevel - return pmceString + pmce_string = self.EXTENSION_NAME + if self.accept_max_compress_level: + pmce_string += "; client_max_compress_level" + if self.request_max_compress_level != 0: + pmce_string += "; server_max_compress_level=%d" % self.request_max_compress_level + return pmce_string def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, - 'acceptMaxCompressLevel': self.acceptMaxCompressLevel, - 'requestMaxCompressLevel': self.requestMaxCompressLevel} + 'accept_max_compress_level': self.accept_max_compress_level, + 'request_max_compress_level': self.request_max_compress_level} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageBzip2Offer(acceptMaxCompressLevel = %s, requestMaxCompressLevel = %s)" % (self.acceptMaxCompressLevel, self.requestMaxCompressLevel) + return "PerMessageBzip2Offer(accept_max_compress_level = %s, request_max_compress_level = %s)" % (self.accept_max_compress_level, self.request_max_compress_level) class PerMessageBzip2OfferAccept(PerMessageCompressOfferAccept, PerMessageBzip2Mixin): @@ -176,71 +176,74 @@ class PerMessageBzip2OfferAccept(PerMessageCompressOfferAccept, PerMessageBzip2M def __init__(self, offer, - requestMaxCompressLevel=0, - compressLevel=None): + request_max_compress_level=0, + compress_level=None): """ Constructor. :param offer: The offer being accepted. :type offer: Instance of :class:`autobahn.compress.PerMessageBzip2Offer`. - :param requestMaxCompressLevel: Iff non-zero, server requests given "maximum compression level" - must be 1-9. - :type requestMaxCompressLevel: int - :param compressLevel: Override server ("server-to-client direction") compress level (this must be compatible with offer). - :type compressLevel: int + :param request_max_compress_level: Iff non-zero, server requests given "maximum compression level" - must be 1-9. + :type request_max_compress_level: int + :param compress_level: Override server ("server-to-client direction") compress level (this must be compatible with offer). + :type compress_level: int """ if not isinstance(offer, PerMessageBzip2Offer): raise Exception("invalid type %s for offer" % type(offer)) self.offer = offer - if requestMaxCompressLevel != 0 and requestMaxCompressLevel not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for requestMaxCompressLevel - permissible values %s" % (requestMaxCompressLevel, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) + if request_max_compress_level != 0 and request_max_compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for request_max_compress_level - permissible values %s" % (request_max_compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) - if requestMaxCompressLevel != 0 and not offer.acceptMaxCompressLevel: - raise Exception("invalid value %s for requestMaxCompressLevel - feature unsupported by client" % requestMaxCompressLevel) + if request_max_compress_level != 0 and not offer.accept_max_compress_level: + raise Exception("invalid value %s for request_max_compress_level - feature unsupported by client" % request_max_compress_level) - self.requestMaxCompressLevel = requestMaxCompressLevel + self.request_max_compress_level = request_max_compress_level - if compressLevel is not None: - if compressLevel not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for compressLevel - permissible values %s" % (compressLevel, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) + if compress_level is not None: + if compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for compress_level - permissible values %s" % (compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) - if offer.requestMaxCompressLevel != 0 and compressLevel > offer.requestMaxCompressLevel: - raise Exception("invalid value %s for compressLevel - client requested lower maximum value" % compressLevel) + if offer.request_max_compress_level != 0 and compress_level > offer.request_max_compress_level: + raise Exception("invalid value %s for compress_level - client requested lower maximum value" % compress_level) - self.compressLevel = compressLevel + self.compress_level = compress_level - def getExtensionString(self): + def get_extension_string(self): """ Returns the WebSocket extension configuration string as sent to the server. - :returns: str -- PMCE configuration string. + :returns: PMCE configuration string. + :rtype: str """ - pmceString = self.EXTENSION_NAME - if self.offer.requestMaxCompressLevel != 0: - pmceString += "; server_max_compress_level=%d" % self.offer.requestMaxCompressLevel - if self.requestMaxCompressLevel != 0: - pmceString += "; client_max_compress_level=%d" % self.requestMaxCompressLevel - return pmceString + pmce_string = self.EXTENSION_NAME + if self.offer.request_max_compress_level != 0: + pmce_string += "; server_max_compress_level=%d" % self.offer.request_max_compress_level + if self.request_max_compress_level != 0: + pmce_string += "; client_max_compress_level=%d" % self.request_max_compress_level + return pmce_string def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'offer': self.offer.__json__(), - 'requestMaxCompressLevel': self.requestMaxCompressLevel, - 'compressLevel': self.compressLevel} + 'request_max_compress_level': self.request_max_compress_level, + 'compress_level': self.compress_level} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageBzip2Accept(offer = %s, requestMaxCompressLevel = %s, compressLevel = %s)" % (self.offer.__repr__(), self.requestMaxCompressLevel, self.compressLevel) + return "PerMessageBzip2Accept(offer = %s, request_max_compress_level = %s, compress_level = %s)" % (self.offer.__repr__(), self.request_max_compress_level, self.compress_level) class PerMessageBzip2Response(PerMessageCompressResponse, PerMessageBzip2Mixin): @@ -256,7 +259,8 @@ class PerMessageBzip2Response(PerMessageCompressResponse, PerMessageBzip2Mixin): :param params: Output from :func:`autobahn.websocket.WebSocketProtocol._parseExtensionsHeader`. :type params: list - :returns: object -- A new instance of :class:`autobahn.compress.PerMessageBzip2Response`. + :returns: A new instance of :class:`autobahn.compress.PerMessageBzip2Response`. + :rtype: obj """ client_max_compress_level = 0 server_max_compress_level = 0 @@ -305,7 +309,8 @@ class PerMessageBzip2Response(PerMessageCompressResponse, PerMessageBzip2Mixin): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'client_max_compress_level': self.client_max_compress_level, @@ -315,7 +320,8 @@ class PerMessageBzip2Response(PerMessageCompressResponse, PerMessageBzip2Mixin): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ return "PerMessageBzip2Response(client_max_compress_level = %s, server_max_compress_level = %s)" % (self.client_max_compress_level, self.server_max_compress_level) @@ -328,46 +334,47 @@ class PerMessageBzip2ResponseAccept(PerMessageCompressResponseAccept, PerMessage def __init__(self, response, - compressLevel=None): + compress_level=None): """ - Constructor. :param response: The response being accepted. :type response: Instance of :class:`autobahn.compress.PerMessageBzip2Response`. - :param compressLevel: Override client ("client-to-server direction") compress level (this must be compatible with response). - :type compressLevel: int + :param compress_level: Override client ("client-to-server direction") compress level (this must be compatible with response). + :type compress_level: int """ if not isinstance(response, PerMessageBzip2Response): raise Exception("invalid type %s for response" % type(response)) self.response = response - if compressLevel is not None: - if compressLevel not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for compressLevel - permissible values %s" % (compressLevel, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) + if compress_level is not None: + if compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for compress_level - permissible values %s" % (compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES)) - if response.client_max_compress_level != 0 and compressLevel > response.client_max_compress_level: - raise Exception("invalid value %s for compressLevel - server requested lower maximum value" % compressLevel) + if response.client_max_compress_level != 0 and compress_level > response.client_max_compress_level: + raise Exception("invalid value %s for compress_level - server requested lower maximum value" % compress_level) - self.compressLevel = compressLevel + self.compress_level = compress_level def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'response': self.response.__json__(), - 'compressLevel': self.compressLevel} + 'compress_level': self.compress_level} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageBzip2ResponseAccept(response = %s, compressLevel = %s)" % (self.response.__repr__(), self.compressLevel) + return "PerMessageBzip2ResponseAccept(response = %s, compress_level = %s)" % (self.response.__repr__(), self.compress_level) class PerMessageBzip2(PerMessageCompress, PerMessageBzip2Mixin): @@ -377,24 +384,24 @@ class PerMessageBzip2(PerMessageCompress, PerMessageBzip2Mixin): DEFAULT_COMPRESS_LEVEL = 9 @classmethod - def createFromResponseAccept(cls, isServer, accept): - pmce = cls(isServer, + def create_from_response_accept(cls, is_server, accept): + pmce = cls(is_server, accept.response.server_max_compress_level, - accept.compressLevel if accept.compressLevel is not None else accept.response.client_max_compress_level) + accept.compress_level if accept.compress_level is not None else accept.response.client_max_compress_level) return pmce @classmethod - def createFromOfferAccept(cls, isServer, accept): - pmce = cls(isServer, - accept.compressLevel if accept.compressLevel is not None else accept.offer.requestMaxCompressLevel, - accept.requestMaxCompressLevel) + def create_from_offer_accept(cls, is_server, accept): + pmce = cls(is_server, + accept.compress_level if accept.compress_level is not None else accept.offer.request_max_compress_level, + accept.request_max_compress_level) return pmce def __init__(self, - isServer, + is_server, server_max_compress_level, client_max_compress_level): - self._isServer = isServer + self._isServer = is_server self._compressor = None self._decompressor = None @@ -410,7 +417,7 @@ class PerMessageBzip2(PerMessageCompress, PerMessageBzip2Mixin): def __repr__(self): return "PerMessageBzip2(isServer = %s, server_max_compress_level = %s, client_max_compress_level = %s)" % (self._isServer, self.server_max_compress_level, self.client_max_compress_level) - def startCompressMessage(self): + def start_compress_message(self): if self._isServer: if self._compressor is None: self._compressor = bz2.BZ2Compressor(self.server_max_compress_level) @@ -418,10 +425,10 @@ class PerMessageBzip2(PerMessageCompress, PerMessageBzip2Mixin): if self._compressor is None: self._compressor = bz2.BZ2Compressor(self.client_max_compress_level) - def compressMessageData(self, data): + def compress_message_data(self, data): return self._compressor.compress(data) - def endCompressMessage(self): + def end_compress_message(self): data = self._compressor.flush() # there seems to be no "flush without close stream", and after @@ -430,12 +437,12 @@ class PerMessageBzip2(PerMessageCompress, PerMessageBzip2Mixin): return data - def startDecompressMessage(self): + def start_decompress_message(self): if self._decompressor is None: self._decompressor = bz2.BZ2Decompressor() - def decompressMessageData(self, data): + def decompress_message_data(self, data): return self._decompressor.decompress(data) - def endDecompressMessage(self): + def end_decompress_message(self): self._decompressor = None diff --git a/autobahn/websocket/compress_deflate.py b/autobahn/websocket/compress_deflate.py index 9ea1a9aa..bfc36bd7 100644 --- a/autobahn/websocket/compress_deflate.py +++ b/autobahn/websocket/compress_deflate.py @@ -28,6 +28,7 @@ from __future__ import absolute_import import zlib +from autobahn.util import public from autobahn.websocket.compress_base import PerMessageCompressOffer, \ PerMessageCompressOfferAccept, \ PerMessageCompressResponse, \ @@ -51,22 +52,23 @@ class PerMessageDeflateMixin(object): EXTENSION_NAME = "permessage-deflate" """ - Name of this WebSocket extension. - """ + Name of this WebSocket extension. + """ WINDOW_SIZE_PERMISSIBLE_VALUES = [8, 9, 10, 11, 12, 13, 14, 15] """ - Permissible value for window size parameter. - Higher values use more memory, but produce smaller output. The default is 15. - """ + Permissible value for window size parameter. + Higher values use more memory, but produce smaller output. The default is 15. + """ MEM_LEVEL_PERMISSIBLE_VALUES = [1, 2, 3, 4, 5, 6, 7, 8, 9] """ - Permissible value for memory level parameter. - Higher values use more memory, but are faster and produce smaller output. The default is 8. - """ + Permissible value for memory level parameter. + Higher values use more memory, but are faster and produce smaller output. The default is 8. + """ +@public class PerMessageDeflateOffer(PerMessageCompressOffer, PerMessageDeflateMixin): """ Set of extension parameters for `permessage-deflate` WebSocket extension @@ -81,15 +83,16 @@ class PerMessageDeflateOffer(PerMessageCompressOffer, PerMessageDeflateMixin): :param params: Output from :func:`autobahn.websocket.WebSocketProtocol._parseExtensionsHeader`. :type params: list - :returns: object -- A new instance of :class:`autobahn.compress.PerMessageDeflateOffer`. + :returns: A new instance of :class:`autobahn.compress.PerMessageDeflateOffer`. + :rtype: obj """ # extension parameter defaults - acceptMaxWindowBits = False - acceptNoContextTakeover = True - # acceptNoContextTakeover = False # FIXME: this may change in draft - requestMaxWindowBits = 0 - requestNoContextTakeover = False + accept_max_window_bits = False + accept_no_context_takeover = True + # accept_no_context_takeover = False # FIXME: this may change in draft + request_max_window_bits = 0 + request_no_context_takeover = False # verify/parse client ("client-to-server direction") parameters of permessage-deflate offer for p in params: @@ -100,7 +103,7 @@ class PerMessageDeflateOffer(PerMessageCompressOffer, PerMessageDeflateMixin): val = params[p][0] if p == 'client_max_window_bits': - ## + # # see: https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-18 # 8.1.2.2. client_max_window_bits @@ -118,17 +121,17 @@ class PerMessageDeflateOffer(PerMessageCompressOffer, PerMessageDeflateMixin): raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: # FIXME (maybe): possibly forward/process the client hint! - # acceptMaxWindowBits = val - acceptMaxWindowBits = True + # accept_max_window_bits = val + accept_max_window_bits = True else: - acceptMaxWindowBits = True + accept_max_window_bits = True elif p == 'client_no_context_takeover': # noinspection PySimplifyBooleanCheck if val is not True: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - acceptNoContextTakeover = True + accept_no_context_takeover = True elif p == 'server_max_window_bits': try: @@ -139,99 +142,103 @@ class PerMessageDeflateOffer(PerMessageCompressOffer, PerMessageDeflateMixin): if val not in PerMessageDeflateMixin.WINDOW_SIZE_PERMISSIBLE_VALUES: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - requestMaxWindowBits = val + request_max_window_bits = val elif p == 'server_no_context_takeover': # noinspection PySimplifyBooleanCheck if val is not True: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - requestNoContextTakeover = True + request_no_context_takeover = True else: raise Exception("illegal extension parameter '%s' for extension '%s'" % (p, cls.EXTENSION_NAME)) - offer = cls(acceptNoContextTakeover, - acceptMaxWindowBits, - requestNoContextTakeover, - requestMaxWindowBits) + offer = cls(accept_no_context_takeover, + accept_max_window_bits, + request_no_context_takeover, + request_max_window_bits) return offer def __init__(self, - acceptNoContextTakeover=True, - acceptMaxWindowBits=True, - requestNoContextTakeover=False, - requestMaxWindowBits=0): + accept_no_context_takeover=True, + accept_max_window_bits=True, + request_no_context_takeover=False, + request_max_window_bits=0): """ - Constructor. - :param acceptNoContextTakeover: Iff true, client accepts "no context takeover" feature. - :type acceptNoContextTakeover: bool - :param acceptMaxWindowBits: Iff true, client accepts setting "max window size". - :type acceptMaxWindowBits: bool - :param requestNoContextTakeover: Iff true, client request "no context takeover" feature. - :type requestNoContextTakeover: bool - :param requestMaxWindowBits: Iff non-zero, client requests given "max window size" - must be 8-15. - :type requestMaxWindowBits: int + :param accept_no_context_takeover: When ``True``, the client accepts the "no context takeover" feature. + :type accept_no_context_takeover: bool + :param accept_max_window_bits: When ``True``, the client accepts setting "max window size". + :type accept_max_window_bits: bool + :param request_no_context_takeover: When ``True``, the client request the "no context takeover" feature. + :type request_no_context_takeover: bool + :param request_max_window_bits: When non-zero, the client requests the given "max window size" (must be + and integer from the interval ``[8..15]``). + :type request_max_window_bits: int """ - if type(acceptNoContextTakeover) != bool: - raise Exception("invalid type %s for acceptNoContextTakeover" % type(acceptNoContextTakeover)) + if type(accept_no_context_takeover) != bool: + raise Exception("invalid type %s for accept_no_context_takeover" % type(accept_no_context_takeover)) - self.acceptNoContextTakeover = acceptNoContextTakeover + self.accept_no_context_takeover = accept_no_context_takeover - if type(acceptMaxWindowBits) != bool: - raise Exception("invalid type %s for acceptMaxWindowBits" % type(acceptMaxWindowBits)) + if type(accept_max_window_bits) != bool: + raise Exception("invalid type %s for accept_max_window_bits" % type(accept_max_window_bits)) - self.acceptMaxWindowBits = acceptMaxWindowBits + self.accept_max_window_bits = accept_max_window_bits - if type(requestNoContextTakeover) != bool: - raise Exception("invalid type %s for requestNoContextTakeover" % type(requestNoContextTakeover)) + if type(request_no_context_takeover) != bool: + raise Exception("invalid type %s for request_no_context_takeover" % type(request_no_context_takeover)) - self.requestNoContextTakeover = requestNoContextTakeover + self.request_no_context_takeover = request_no_context_takeover - if requestMaxWindowBits != 0 and requestMaxWindowBits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for requestMaxWindowBits - permissible values %s" % (requestMaxWindowBits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) + if request_max_window_bits != 0 and request_max_window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for request_max_window_bits - permissible values %s" % (request_max_window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) - self.requestMaxWindowBits = requestMaxWindowBits + self.request_max_window_bits = request_max_window_bits - def getExtensionString(self): + def get_extension_string(self): """ Returns the WebSocket extension configuration string as sent to the server. - :returns: str -- PMCE configuration string. + :returns: PMCE configuration string. + :rtype: str """ - pmceString = self.EXTENSION_NAME - if self.acceptNoContextTakeover: - pmceString += "; client_no_context_takeover" - if self.acceptMaxWindowBits: - pmceString += "; client_max_window_bits" - if self.requestNoContextTakeover: - pmceString += "; server_no_context_takeover" - if self.requestMaxWindowBits != 0: - pmceString += "; server_max_window_bits=%d" % self.requestMaxWindowBits - return pmceString + pmce_string = self.EXTENSION_NAME + if self.accept_no_context_takeover: + pmce_string += "; client_no_context_takeover" + if self.accept_max_window_bits: + pmce_string += "; client_max_window_bits" + if self.request_no_context_takeover: + pmce_string += "; server_no_context_takeover" + if self.request_max_window_bits != 0: + pmce_string += "; server_max_window_bits=%d" % self.request_max_window_bits + return pmce_string def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, - 'acceptNoContextTakeover': self.acceptNoContextTakeover, - 'acceptMaxWindowBits': self.acceptMaxWindowBits, - 'requestNoContextTakeover': self.requestNoContextTakeover, - 'requestMaxWindowBits': self.requestMaxWindowBits} + 'accept_no_context_takeover': self.accept_no_context_takeover, + 'accept_max_window_bits': self.accept_max_window_bits, + 'request_no_context_takeover': self.request_no_context_takeover, + 'request_max_window_bits': self.request_max_window_bits} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageDeflateOffer(acceptNoContextTakeover = %s, acceptMaxWindowBits = %s, requestNoContextTakeover = %s, requestMaxWindowBits = %s)" % (self.acceptNoContextTakeover, self.acceptMaxWindowBits, self.requestNoContextTakeover, self.requestMaxWindowBits) + return "PerMessageDeflateOffer(accept_no_context_takeover = %s, accept_max_window_bits = %s, request_no_context_takeover = %s, request_max_window_bits = %s)" % (self.accept_no_context_takeover, self.accept_max_window_bits, self.request_no_context_takeover, self.request_max_window_bits) +@public class PerMessageDeflateOfferAccept(PerMessageCompressOfferAccept, PerMessageDeflateMixin): """ Set of parameters with which to accept an `permessage-deflate` offer @@ -240,112 +247,118 @@ class PerMessageDeflateOfferAccept(PerMessageCompressOfferAccept, PerMessageDefl def __init__(self, offer, - requestNoContextTakeover=False, - requestMaxWindowBits=0, - noContextTakeover=None, - windowBits=None, - memLevel=None): + request_no_context_takeover=False, + request_max_window_bits=0, + no_context_takeover=None, + window_bits=None, + mem_level=None): """ - Constructor. :param offer: The offer being accepted. :type offer: Instance of :class:`autobahn.compress.PerMessageDeflateOffer`. - :param requestNoContextTakeover: Iff true, server request "no context takeover" feature. - :type requestNoContextTakeover: bool - :param requestMaxCompressLevel: Iff non-zero, server requests given "maximum compression level" - must be 1-9. - :type requestMaxCompressLevel: int - :param noContextTakeover: Override server ("server-to-client direction") context takeover (this must be compatible with offer). - :type noContextTakeover: bool - :param windowBits: Override server ("server-to-client direction") window size (this must be compatible with offer). - :type windowBits: int - :param memLevel: Set server ("server-to-client direction") memory level. - :type memLevel: int + :param request_no_context_takeover: When ``True``, the server requests the "no context takeover" feature. + :type request_no_context_takeover: bool + :param request_max_window_bits: When non-zero, the server requests the given "max window size" (must be + and integer from the interval ``[8..15]``). + :param request_max_window_bits: int + :param no_context_takeover: Override server ("server-to-client direction") context takeover (this must + be compatible with the offer). + :type no_context_takeover: bool + :param window_bits: Override server ("server-to-client direction") window size (this must be + compatible with the offer). + :type window_bits: int + :param mem_level: Set server ("server-to-client direction") memory level. + :type mem_level: int """ if not isinstance(offer, PerMessageDeflateOffer): raise Exception("invalid type %s for offer" % type(offer)) self.offer = offer - if type(requestNoContextTakeover) != bool: - raise Exception("invalid type %s for requestNoContextTakeover" % type(requestNoContextTakeover)) + if type(request_no_context_takeover) != bool: + raise Exception("invalid type %s for request_no_context_takeover" % type(request_no_context_takeover)) - if requestNoContextTakeover and not offer.acceptNoContextTakeover: - raise Exception("invalid value %s for requestNoContextTakeover - feature unsupported by client" % requestNoContextTakeover) + if request_no_context_takeover and not offer.accept_no_context_takeover: + raise Exception("invalid value %s for request_no_context_takeover - feature unsupported by client" % request_no_context_takeover) - self.requestNoContextTakeover = requestNoContextTakeover + self.request_no_context_takeover = request_no_context_takeover - if requestMaxWindowBits != 0 and requestMaxWindowBits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for requestMaxWindowBits - permissible values %s" % (requestMaxWindowBits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) + if request_max_window_bits != 0 and request_max_window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for request_max_window_bits - permissible values %s" % (request_max_window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) - if requestMaxWindowBits != 0 and not offer.acceptMaxWindowBits: - raise Exception("invalid value %s for requestMaxWindowBits - feature unsupported by client" % requestMaxWindowBits) + if request_max_window_bits != 0 and not offer.accept_max_window_bits: + raise Exception("invalid value %s for request_max_window_bits - feature unsupported by client" % request_max_window_bits) - self.requestMaxWindowBits = requestMaxWindowBits + self.request_max_window_bits = request_max_window_bits - if noContextTakeover is not None: - if type(noContextTakeover) != bool: - raise Exception("invalid type %s for noContextTakeover" % type(noContextTakeover)) + if no_context_takeover is not None: + if type(no_context_takeover) != bool: + raise Exception("invalid type %s for no_context_takeover" % type(no_context_takeover)) - if offer.requestNoContextTakeover and not noContextTakeover: - raise Exception("invalid value %s for noContextTakeover - client requested feature" % noContextTakeover) + if offer.request_no_context_takeover and not no_context_takeover: + raise Exception("invalid value %s for no_context_takeover - client requested feature" % no_context_takeover) - self.noContextTakeover = noContextTakeover + self.no_context_takeover = no_context_takeover - if windowBits is not None: - if windowBits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for windowBits - permissible values %s" % (windowBits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) + if window_bits is not None: + if window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for window_bits - permissible values %s" % (window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) - if offer.requestMaxWindowBits != 0 and windowBits > offer.requestMaxWindowBits: - raise Exception("invalid value %s for windowBits - client requested lower maximum value" % windowBits) + if offer.request_max_window_bits != 0 and window_bits > offer.request_max_window_bits: + raise Exception("invalid value %s for window_bits - client requested lower maximum value" % window_bits) - self.windowBits = windowBits + self.window_bits = window_bits - if memLevel is not None: - if memLevel not in self.MEM_LEVEL_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for memLevel - permissible values %s" % (memLevel, self.MEM_LEVEL_PERMISSIBLE_VALUES)) + if mem_level is not None: + if mem_level not in self.MEM_LEVEL_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for mem_level - permissible values %s" % (mem_level, self.MEM_LEVEL_PERMISSIBLE_VALUES)) - self.memLevel = memLevel + self.mem_level = mem_level - def getExtensionString(self): + def get_extension_string(self): """ Returns the WebSocket extension configuration string as sent to the server. - :returns: str -- PMCE configuration string. + :returns: PMCE configuration string. + :rtype: str """ - pmceString = self.EXTENSION_NAME - if self.offer.requestNoContextTakeover: - pmceString += "; server_no_context_takeover" - if self.offer.requestMaxWindowBits != 0: - pmceString += "; server_max_window_bits=%d" % self.offer.requestMaxWindowBits - if self.requestNoContextTakeover: - pmceString += "; client_no_context_takeover" - if self.requestMaxWindowBits != 0: - pmceString += "; client_max_window_bits=%d" % self.requestMaxWindowBits - return pmceString + pmce_string = self.EXTENSION_NAME + if self.offer.request_no_context_takeover: + pmce_string += "; server_no_context_takeover" + if self.offer.request_max_window_bits != 0: + pmce_string += "; server_max_window_bits=%d" % self.offer.request_max_window_bits + if self.request_no_context_takeover: + pmce_string += "; client_no_context_takeover" + if self.request_max_window_bits != 0: + pmce_string += "; client_max_window_bits=%d" % self.request_max_window_bits + return pmce_string def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'offer': self.offer.__json__(), - 'requestNoContextTakeover': self.requestNoContextTakeover, - 'requestMaxWindowBits': self.requestMaxWindowBits, - 'noContextTakeover': self.noContextTakeover, - 'windowBits': self.windowBits, - 'memLevel': self.memLevel} + 'request_no_context_takeover': self.request_no_context_takeover, + 'request_max_window_bits': self.request_max_window_bits, + 'no_context_takeover': self.no_context_takeover, + 'window_bits': self.window_bits, + 'mem_level': self.mem_level} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageDeflateOfferAccept(offer = %s, requestNoContextTakeover = %s, requestMaxWindowBits = %s, noContextTakeover = %s, windowBits = %s, memLevel = %s)" % (self.offer.__repr__(), self.requestNoContextTakeover, self.requestMaxWindowBits, self.noContextTakeover, self.windowBits, self.memLevel) + return "PerMessageDeflateOfferAccept(offer = %s, request_no_context_takeover = %s, request_max_window_bits = %s, no_context_takeover = %s, window_bits = %s, mem_level = %s)" % (self.offer.__repr__(), self.request_no_context_takeover, self.request_max_window_bits, self.no_context_takeover, self.window_bits, self.mem_level) +@public class PerMessageDeflateResponse(PerMessageCompressResponse, PerMessageDeflateMixin): """ Set of parameters for `permessage-deflate` responded by server. @@ -359,7 +372,8 @@ class PerMessageDeflateResponse(PerMessageCompressResponse, PerMessageDeflateMix :param params: Output from :func:`autobahn.websocket.WebSocketProtocol._parseExtensionsHeader`. :type params: list - :returns: object -- A new instance of :class:`autobahn.compress.PerMessageDeflateResponse`. + :returns: A new instance of :class:`autobahn.compress.PerMessageDeflateResponse`. + :rtype: obj """ client_max_window_bits = 0 client_no_context_takeover = False @@ -423,6 +437,17 @@ class PerMessageDeflateResponse(PerMessageCompressResponse, PerMessageDeflateMix client_no_context_takeover, server_max_window_bits, server_no_context_takeover): + """ + + :param client_max_window_bits: FIXME + :type client_max_window_bits: int + :param client_no_context_takeover: FIXME + :type client_no_context_takeover: bool + :param server_max_window_bits: FIXME + :type server_max_window_bits: int + :param server_no_context_takeover: FIXME + :type server_no_context_takeover: bool + """ self.client_max_window_bits = client_max_window_bits self.client_no_context_takeover = client_no_context_takeover self.server_max_window_bits = server_max_window_bits @@ -432,7 +457,8 @@ class PerMessageDeflateResponse(PerMessageCompressResponse, PerMessageDeflateMix """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'client_max_window_bits': self.client_max_window_bits, @@ -444,11 +470,13 @@ class PerMessageDeflateResponse(PerMessageCompressResponse, PerMessageDeflateMix """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ return "PerMessageDeflateResponse(client_max_window_bits = %s, client_no_context_takeover = %s, server_max_window_bits = %s, server_no_context_takeover = %s)" % (self.client_max_window_bits, self.client_no_context_takeover, self.server_max_window_bits, self.server_no_context_takeover) +@public class PerMessageDeflateResponseAccept(PerMessageCompressResponseAccept, PerMessageDeflateMixin): """ Set of parameters with which to accept an `permessage-deflate` response @@ -457,69 +485,70 @@ class PerMessageDeflateResponseAccept(PerMessageCompressResponseAccept, PerMessa def __init__(self, response, - noContextTakeover=None, - windowBits=None, - memLevel=None): + no_context_takeover=None, + window_bits=None, + mem_level=None): """ - Constructor. :param response: The response being accepted. :type response: Instance of :class:`autobahn.compress.PerMessageDeflateResponse`. - :param noContextTakeover: Override client ("client-to-server direction") context takeover (this must be compatible with response). - :type noContextTakeover: bool - :param windowBits: Override client ("client-to-server direction") window size (this must be compatible with response). - :type windowBits: int - :param memLevel: Set client ("client-to-server direction") memory level. - :type memLevel: int + :param no_context_takeover: Override client ("client-to-server direction") context takeover (this must be compatible with response). + :type no_context_takeover: bool + :param window_bits: Override client ("client-to-server direction") window size (this must be compatible with response). + :type window_bits: int + :param mem_level: Set client ("client-to-server direction") memory level. + :type mem_level: int """ if not isinstance(response, PerMessageDeflateResponse): raise Exception("invalid type %s for response" % type(response)) self.response = response - if noContextTakeover is not None: - if type(noContextTakeover) != bool: - raise Exception("invalid type %s for noContextTakeover" % type(noContextTakeover)) + if no_context_takeover is not None: + if type(no_context_takeover) != bool: + raise Exception("invalid type %s for no_context_takeover" % type(no_context_takeover)) - if response.client_no_context_takeover and not noContextTakeover: - raise Exception("invalid value %s for noContextTakeover - server requested feature" % noContextTakeover) + if response.client_no_context_takeover and not no_context_takeover: + raise Exception("invalid value %s for no_context_takeover - server requested feature" % no_context_takeover) - self.noContextTakeover = noContextTakeover + self.no_context_takeover = no_context_takeover - if windowBits is not None: - if windowBits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for windowBits - permissible values %s" % (windowBits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) + if window_bits is not None: + if window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for window_bits - permissible values %s" % (window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES)) - if response.client_max_window_bits != 0 and windowBits > response.client_max_window_bits: - raise Exception("invalid value %s for windowBits - server requested lower maximum value" % windowBits) + if response.client_max_window_bits != 0 and window_bits > response.client_max_window_bits: + raise Exception("invalid value %s for window_bits - server requested lower maximum value" % window_bits) - self.windowBits = windowBits + self.window_bits = window_bits - if memLevel is not None: - if memLevel not in self.MEM_LEVEL_PERMISSIBLE_VALUES: - raise Exception("invalid value %s for memLevel - permissible values %s" % (memLevel, self.MEM_LEVEL_PERMISSIBLE_VALUES)) + if mem_level is not None: + if mem_level not in self.MEM_LEVEL_PERMISSIBLE_VALUES: + raise Exception("invalid value %s for mem_level - permissible values %s" % (mem_level, self.MEM_LEVEL_PERMISSIBLE_VALUES)) - self.memLevel = memLevel + self.mem_level = mem_level def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'response': self.response.__json__(), - 'noContextTakeover': self.noContextTakeover, - 'windowBits': self.windowBits, - 'memLevel': self.memLevel} + 'no_context_takeover': self.no_context_takeover, + 'window_bits': self.window_bits, + 'mem_level': self.mem_level} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageDeflateResponseAccept(response = %s, noContextTakeover = %s, windowBits = %s, memLevel = %s)" % (self.response.__repr__(), self.noContextTakeover, self.windowBits, self.memLevel) + return "PerMessageDeflateResponseAccept(response = %s, no_context_takeover = %s, window_bits = %s, mem_level = %s)" % (self.response.__repr__(), self.no_context_takeover, self.window_bits, self.mem_level) # noinspection PyArgumentList @@ -531,35 +560,35 @@ class PerMessageDeflate(PerMessageCompress, PerMessageDeflateMixin): DEFAULT_MEM_LEVEL = 8 @classmethod - def createFromResponseAccept(cls, isServer, accept): + def create_from_response_accept(cls, is_server, accept): # accept: instance of PerMessageDeflateResponseAccept - pmce = cls(isServer, + pmce = cls(is_server, accept.response.server_no_context_takeover, - accept.noContextTakeover if accept.noContextTakeover is not None else accept.response.client_no_context_takeover, + accept.no_context_takeover if accept.no_context_takeover is not None else accept.response.client_no_context_takeover, accept.response.server_max_window_bits, - accept.windowBits if accept.windowBits is not None else accept.response.client_max_window_bits, + accept.window_bits if accept.window_bits is not None else accept.response.client_max_window_bits, accept.memLevel) return pmce @classmethod - def createFromOfferAccept(cls, isServer, accept): + def create_from_offer_accept(cls, is_server, accept): # accept: instance of PerMessageDeflateOfferAccept - pmce = cls(isServer, - accept.noContextTakeover if accept.noContextTakeover is not None else accept.offer.requestNoContextTakeover, - accept.requestNoContextTakeover, - accept.windowBits if accept.windowBits is not None else accept.offer.requestMaxWindowBits, + pmce = cls(is_server, + accept.no_context_takeover if accept.no_context_takeover is not None else accept.offer.request_no_context_takeover, + accept.request_no_context_takeover, + accept.window_bits if accept.window_bits is not None else accept.offer.requestMaxWindowBits, accept.requestMaxWindowBits, accept.memLevel) return pmce def __init__(self, - isServer, + is_server, server_no_context_takeover, client_no_context_takeover, server_max_window_bits, client_max_window_bits, mem_level): - self._isServer = isServer + self._is_server = is_server self.server_no_context_takeover = server_no_context_takeover self.client_no_context_takeover = client_no_context_takeover @@ -574,7 +603,7 @@ class PerMessageDeflate(PerMessageCompress, PerMessageDeflateMixin): def __json__(self): return {'extension': self.EXTENSION_NAME, - 'isServer': self._isServer, + 'is_server': self._is_server, 'server_no_context_takeover': self.server_no_context_takeover, 'client_no_context_takeover': self.client_no_context_takeover, 'server_max_window_bits': self.server_max_window_bits, @@ -582,38 +611,38 @@ class PerMessageDeflate(PerMessageCompress, PerMessageDeflateMixin): 'mem_level': self.mem_level} def __repr__(self): - return "PerMessageDeflate(isServer = %s, server_no_context_takeover = %s, client_no_context_takeover = %s, server_max_window_bits = %s, client_max_window_bits = %s, mem_level = %s)" % (self._isServer, self.server_no_context_takeover, self.client_no_context_takeover, self.server_max_window_bits, self.client_max_window_bits, self.mem_level) + return "PerMessageDeflate(is_server = %s, server_no_context_takeover = %s, client_no_context_takeover = %s, server_max_window_bits = %s, client_max_window_bits = %s, mem_level = %s)" % (self._is_server, self.server_no_context_takeover, self.client_no_context_takeover, self.server_max_window_bits, self.client_max_window_bits, self.mem_level) - def startCompressMessage(self): + def start_compress_message(self): # compressobj([level[, method[, wbits[, memlevel[, strategy]]]]]) # http://bugs.python.org/issue19278 # http://hg.python.org/cpython/rev/c54c8e71b79a - if self._isServer: + if self._is_server: if self._compressor is None or self.server_no_context_takeover: self._compressor = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -self.server_max_window_bits, self.mem_level) else: if self._compressor is None or self.client_no_context_takeover: self._compressor = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -self.client_max_window_bits, self.mem_level) - def compressMessageData(self, data): + def compress_message_data(self, data): return self._compressor.compress(data) - def endCompressMessage(self): + def end_compress_message(self): data = self._compressor.flush(zlib.Z_SYNC_FLUSH) return data[:-4] - def startDecompressMessage(self): - if self._isServer: + def start_decompress_message(self): + if self._is_server: if self._decompressor is None or self.client_no_context_takeover: self._decompressor = zlib.decompressobj(-self.client_max_window_bits) else: if self._decompressor is None or self.server_no_context_takeover: self._decompressor = zlib.decompressobj(-self.server_max_window_bits) - def decompressMessageData(self, data): + def decompress_message_data(self, data): return self._decompressor.decompress(data) - def endDecompressMessage(self): + def end_decompress_message(self): # Eat stripped LEN and NLEN field of a non-compressed block added # for Z_SYNC_FLUSH. self._decompressor.decompress(b'\x00\x00\xff\xff') diff --git a/autobahn/websocket/compress_snappy.py b/autobahn/websocket/compress_snappy.py index 4416c523..cee3d60c 100644 --- a/autobahn/websocket/compress_snappy.py +++ b/autobahn/websocket/compress_snappy.py @@ -51,8 +51,8 @@ class PerMessageSnappyMixin(object): EXTENSION_NAME = "permessage-snappy" """ - Name of this WebSocket extension. - """ + Name of this WebSocket extension. + """ class PerMessageSnappyOffer(PerMessageCompressOffer, PerMessageSnappyMixin): @@ -69,16 +69,14 @@ class PerMessageSnappyOffer(PerMessageCompressOffer, PerMessageSnappyMixin): :param params: Output from :func:`autobahn.websocket.WebSocketProtocol._parseExtensionsHeader`. :type params: list - :returns: object -- A new instance of :class:`autobahn.compress.PerMessageSnappyOffer`. + :returns: A new instance of :class:`autobahn.compress.PerMessageSnappyOffer`. + :rtype: obj """ # extension parameter defaults - ## - acceptNoContextTakeover = False - requestNoContextTakeover = False + accept_no_context_takeover = False + request_no_context_takeover = False - ## # verify/parse client ("client-to-server direction") parameters of permessage-snappy offer - ## for p in params: if len(params[p]) > 1: @@ -91,73 +89,75 @@ class PerMessageSnappyOffer(PerMessageCompressOffer, PerMessageSnappyMixin): if val is not True: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - acceptNoContextTakeover = True + accept_no_context_takeover = True elif p == 'server_no_context_takeover': # noinspection PySimplifyBooleanCheck if val is not True: raise Exception("illegal extension parameter value '%s' for parameter '%s' of extension '%s'" % (val, p, cls.EXTENSION_NAME)) else: - requestNoContextTakeover = True + request_no_context_takeover = True else: raise Exception("illegal extension parameter '%s' for extension '%s'" % (p, cls.EXTENSION_NAME)) - offer = cls(acceptNoContextTakeover, - requestNoContextTakeover) + offer = cls(accept_no_context_takeover, + request_no_context_takeover) return offer def __init__(self, - acceptNoContextTakeover=True, - requestNoContextTakeover=False): + accept_no_context_takeover=True, + request_no_context_takeover=False): """ - Constructor. - :param acceptNoContextTakeover: Iff true, client accepts "no context takeover" feature. - :type acceptNoContextTakeover: bool - :param requestNoContextTakeover: Iff true, client request "no context takeover" feature. - :type requestNoContextTakeover: bool + :param accept_no_context_takeover: Iff true, client accepts "no context takeover" feature. + :type accept_no_context_takeover: bool + :param request_no_context_takeover: Iff true, client request "no context takeover" feature. + :type request_no_context_takeover: bool """ - if type(acceptNoContextTakeover) != bool: - raise Exception("invalid type %s for acceptNoContextTakeover" % type(acceptNoContextTakeover)) + if type(accept_no_context_takeover) != bool: + raise Exception("invalid type %s for accept_no_context_takeover" % type(accept_no_context_takeover)) - self.acceptNoContextTakeover = acceptNoContextTakeover + self.accept_no_context_takeover = accept_no_context_takeover - if type(requestNoContextTakeover) != bool: - raise Exception("invalid type %s for requestNoContextTakeover" % type(requestNoContextTakeover)) + if type(request_no_context_takeover) != bool: + raise Exception("invalid type %s for request_no_context_takeover" % type(request_no_context_takeover)) - self.requestNoContextTakeover = requestNoContextTakeover + self.request_no_context_takeover = request_no_context_takeover - def getExtensionString(self): + def get_extension_string(self): """ Returns the WebSocket extension configuration string as sent to the server. - :returns: str -- PMCE configuration string. + :returns: PMCE configuration string. + :rtype: str """ - pmceString = self.EXTENSION_NAME - if self.acceptNoContextTakeover: - pmceString += "; client_no_context_takeover" - if self.requestNoContextTakeover: - pmceString += "; server_no_context_takeover" - return pmceString + pmce_string = self.EXTENSION_NAME + if self.accept_no_context_takeover: + pmce_string += "; client_no_context_takeover" + if self.request_no_context_takeover: + pmce_string += "; server_no_context_takeover" + return pmce_string def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, - 'acceptNoContextTakeover': self.acceptNoContextTakeover, - 'requestNoContextTakeover': self.requestNoContextTakeover} + 'accept_no_context_takeover': self.accept_no_context_takeover, + 'request_no_context_takeover': self.request_no_context_takeover} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageSnappyOffer(acceptNoContextTakeover = %s, requestNoContextTakeover = %s)" % (self.acceptNoContextTakeover, self.requestNoContextTakeover) + return "PerMessageSnappyOffer(accept_no_context_takeover = %s, request_no_context_takeover = %s)" % (self.accept_no_context_takeover, self.request_no_context_takeover) class PerMessageSnappyOfferAccept(PerMessageCompressOfferAccept, PerMessageSnappyMixin): @@ -168,71 +168,73 @@ class PerMessageSnappyOfferAccept(PerMessageCompressOfferAccept, PerMessageSnapp def __init__(self, offer, - requestNoContextTakeover=False, - noContextTakeover=None): + request_no_context_takeover=False, + no_context_takeover=None): """ - Constructor. :param offer: The offer being accepted. :type offer: Instance of :class:`autobahn.compress.PerMessageSnappyOffer`. - :param requestNoContextTakeover: Iff true, server request "no context takeover" feature. - :type requestNoContextTakeover: bool - :param noContextTakeover: Override server ("server-to-client direction") context takeover (this must be compatible with offer). - :type noContextTakeover: bool + :param request_no_context_takeover: Iff true, server request "no context takeover" feature. + :type request_no_context_takeover: bool + :param no_context_takeover: Override server ("server-to-client direction") context takeover (this must be compatible with offer). + :type no_context_takeover: bool """ if not isinstance(offer, PerMessageSnappyOffer): raise Exception("invalid type %s for offer" % type(offer)) self.offer = offer - if type(requestNoContextTakeover) != bool: - raise Exception("invalid type %s for requestNoContextTakeover" % type(requestNoContextTakeover)) + if type(request_no_context_takeover) != bool: + raise Exception("invalid type %s for request_no_context_takeover" % type(request_no_context_takeover)) - if requestNoContextTakeover and not offer.acceptNoContextTakeover: - raise Exception("invalid value %s for requestNoContextTakeover - feature unsupported by client" % requestNoContextTakeover) + if request_no_context_takeover and not offer.accept_no_context_takeover: + raise Exception("invalid value %s for request_no_context_takeover - feature unsupported by client" % request_no_context_takeover) - self.requestNoContextTakeover = requestNoContextTakeover + self.request_no_context_takeover = request_no_context_takeover - if noContextTakeover is not None: - if type(noContextTakeover) != bool: - raise Exception("invalid type %s for noContextTakeover" % type(noContextTakeover)) + if no_context_takeover is not None: + if type(no_context_takeover) != bool: + raise Exception("invalid type %s for no_context_takeover" % type(no_context_takeover)) - if offer.requestNoContextTakeover and not noContextTakeover: - raise Exception("invalid value %s for noContextTakeover - client requested feature" % noContextTakeover) + if offer.request_no_context_takeover and not no_context_takeover: + raise Exception("invalid value %s for no_context_takeover - client requested feature" % no_context_takeover) - self.noContextTakeover = noContextTakeover + self.no_context_takeover = no_context_takeover - def getExtensionString(self): + def get_extension_string(self): """ Returns the WebSocket extension configuration string as sent to the server. - :returns: str -- PMCE configuration string. + :returns: PMCE configuration string. + :rtype: str """ - pmceString = self.EXTENSION_NAME - if self.offer.requestNoContextTakeover: - pmceString += "; server_no_context_takeover" - if self.requestNoContextTakeover: - pmceString += "; client_no_context_takeover" - return pmceString + pmce_string = self.EXTENSION_NAME + if self.offer.request_no_context_takeover: + pmce_string += "; server_no_context_takeover" + if self.request_no_context_takeover: + pmce_string += "; client_no_context_takeover" + return pmce_string def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'offer': self.offer.__json__(), - 'requestNoContextTakeover': self.requestNoContextTakeover, - 'noContextTakeover': self.noContextTakeover} + 'request_no_context_takeover': self.request_no_context_takeover, + 'no_context_takeover': self.no_context_takeover} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageSnappyAccept(offer = %s, requestNoContextTakeover = %s, noContextTakeover = %s)" % (self.offer.__repr__(), self.requestNoContextTakeover, self.noContextTakeover) + return "PerMessageSnappyAccept(offer = %s, request_no_context_takeover = %s, no_context_takeover = %s)" % (self.offer.__repr__(), self.request_no_context_takeover, self.no_context_takeover) class PerMessageSnappyResponse(PerMessageCompressResponse, PerMessageSnappyMixin): @@ -248,7 +250,8 @@ class PerMessageSnappyResponse(PerMessageCompressResponse, PerMessageSnappyMixin :param params: Output from :func:`autobahn.websocket.WebSocketProtocol._parseExtensionsHeader`. :type params: list - :returns: object -- A new instance of :class:`autobahn.compress.PerMessageSnappyResponse`. + :returns: A new instance of :class:`autobahn.compress.PerMessageSnappyResponse`. + :rtype: obj """ client_no_context_takeover = False server_no_context_takeover = False @@ -291,7 +294,8 @@ class PerMessageSnappyResponse(PerMessageCompressResponse, PerMessageSnappyMixin """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'client_no_context_takeover': self.client_no_context_takeover, @@ -301,7 +305,8 @@ class PerMessageSnappyResponse(PerMessageCompressResponse, PerMessageSnappyMixin """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ return "PerMessageSnappyResponse(client_no_context_takeover = %s, server_no_context_takeover = %s)" % (self.client_no_context_takeover, self.server_no_context_takeover) @@ -314,46 +319,47 @@ class PerMessageSnappyResponseAccept(PerMessageCompressResponseAccept, PerMessag def __init__(self, response, - noContextTakeover=None): + no_context_takeover=None): """ - Constructor. :param response: The response being accepted. :type response: Instance of :class:`autobahn.compress.PerMessageSnappyResponse`. - :param noContextTakeover: Override client ("client-to-server direction") context takeover (this must be compatible with response). - :type noContextTakeover: bool + :param no_context_takeover: Override client ("client-to-server direction") context takeover (this must be compatible with response). + :type no_context_takeover: bool """ if not isinstance(response, PerMessageSnappyResponse): raise Exception("invalid type %s for response" % type(response)) self.response = response - if noContextTakeover is not None: - if type(noContextTakeover) != bool: - raise Exception("invalid type %s for noContextTakeover" % type(noContextTakeover)) + if no_context_takeover is not None: + if type(no_context_takeover) != bool: + raise Exception("invalid type %s for no_context_takeover" % type(no_context_takeover)) - if response.client_no_context_takeover and not noContextTakeover: - raise Exception("invalid value %s for noContextTakeover - server requested feature" % noContextTakeover) + if response.client_no_context_takeover and not no_context_takeover: + raise Exception("invalid value %s for no_context_takeover - server requested feature" % no_context_takeover) - self.noContextTakeover = noContextTakeover + self.no_context_takeover = no_context_takeover def __json__(self): """ Returns a JSON serializable object representation. - :returns: object -- JSON serializable representation. + :returns: JSON serializable representation. + :rtype: dict """ return {'extension': self.EXTENSION_NAME, 'response': self.response.__json__(), - 'noContextTakeover': self.noContextTakeover} + 'no_context_takeover': self.no_context_takeover} def __repr__(self): """ Returns Python object representation that can be eval'ed to reconstruct the object. - :returns: str -- Python string representation. + :returns: Python string representation. + :rtype: str """ - return "PerMessageSnappyResponseAccept(response = %s, noContextTakeover = %s)" % (self.response.__repr__(), self.noContextTakeover) + return "PerMessageSnappyResponseAccept(response = %s, no_context_takeover = %s)" % (self.response.__repr__(), self.no_context_takeover) class PerMessageSnappy(PerMessageCompress, PerMessageSnappyMixin): @@ -362,24 +368,24 @@ class PerMessageSnappy(PerMessageCompress, PerMessageSnappyMixin): """ @classmethod - def createFromResponseAccept(cls, isServer, accept): - pmce = cls(isServer, + def create_from_response_accept(cls, is_server, accept): + pmce = cls(is_server, accept.response.server_no_context_takeover, - accept.noContextTakeover if accept.noContextTakeover is not None else accept.response.client_no_context_takeover) + accept.no_context_takeover if accept.no_context_takeover is not None else accept.response.client_no_context_takeover) return pmce @classmethod - def createFromOfferAccept(cls, isServer, accept): - pmce = cls(isServer, - accept.noContextTakeover if accept.noContextTakeover is not None else accept.offer.requestNoContextTakeover, - accept.requestNoContextTakeover) + def create_from_offer_accept(cls, is_server, accept): + pmce = cls(is_server, + accept.no_context_takeover if accept.no_context_takeover is not None else accept.offer.request_no_context_takeover, + accept.request_no_context_takeover) return pmce def __init__(self, - isServer, + is_server, server_no_context_takeover, client_no_context_takeover): - self._isServer = isServer + self._is_server = is_server self.server_no_context_takeover = server_no_context_takeover self.client_no_context_takeover = client_no_context_takeover @@ -392,32 +398,32 @@ class PerMessageSnappy(PerMessageCompress, PerMessageSnappyMixin): 'client_no_context_takeover': self.client_no_context_takeover} def __repr__(self): - return "PerMessageSnappy(isServer = %s, server_no_context_takeover = %s, client_no_context_takeover = %s)" % (self._isServer, self.server_no_context_takeover, self.client_no_context_takeover) + return "PerMessageSnappy(is_server = %s, server_no_context_takeover = %s, client_no_context_takeover = %s)" % (self._is_server, self.server_no_context_takeover, self.client_no_context_takeover) - def startCompressMessage(self): - if self._isServer: + def start_compress_message(self): + if self._is_server: if self._compressor is None or self.server_no_context_takeover: self._compressor = snappy.StreamCompressor() else: if self._compressor is None or self.client_no_context_takeover: self._compressor = snappy.StreamCompressor() - def compressMessageData(self, data): + def compress_message_data(self, data): return self._compressor.add_chunk(data) - def endCompressMessage(self): + def end_compress_message(self): return "" - def startDecompressMessage(self): - if self._isServer: + def start_decompress_message(self): + if self._is_server: if self._decompressor is None or self.client_no_context_takeover: self._decompressor = snappy.StreamDecompressor() else: if self._decompressor is None or self.server_no_context_takeover: self._decompressor = snappy.StreamDecompressor() - def decompressMessageData(self, data): + def decompress_message_data(self, data): return self._decompressor.decompress(data) - def endDecompressMessage(self): + def end_decompress_message(self): pass diff --git a/autobahn/websocket/protocol.py b/autobahn/websocket/protocol.py index e0339b37..7b4d4720 100755 --- a/autobahn/websocket/protocol.py +++ b/autobahn/websocket/protocol.py @@ -51,7 +51,7 @@ from autobahn.websocket.types import ConnectionRequest, ConnectionResponse, Conn from autobahn.util import Stopwatch, newid, wildcards2patterns, encode_truncate from autobahn.util import _LazyHexFormatter from autobahn.websocket.utf8validator import Utf8Validator -from autobahn.websocket.xormasker import XorMaskerNull, createXorMasker +from autobahn.websocket.xormasker import XorMaskerNull, create_xor_masker from autobahn.websocket.compress import PERMESSAGE_COMPRESSION_EXTENSION from autobahn.websocket.util import parse_url @@ -1483,7 +1483,7 @@ class WebSocketProtocol(object): i += 4 if frame_masked and frame_payload_len > 0 and self.applyMask: - self.current_frame_masker = createXorMasker(frame_mask, frame_payload_len) + self.current_frame_masker = create_xor_masker(frame_mask, frame_payload_len) else: self.current_frame_masker = XorMaskerNull() @@ -1575,7 +1575,7 @@ class WebSocketProtocol(object): # if self._perMessageCompress is not None and self.current_frame.rsv == 4: self._isMessageCompressed = True - self._perMessageCompress.startDecompressMessage() + self._perMessageCompress.start_decompress_message() else: self._isMessageCompressed = False @@ -1616,7 +1616,7 @@ class WebSocketProtocol(object): octets=_LazyHexFormatter(payload), ) - payload = self._perMessageCompress.decompressMessageData(payload) + payload = self._perMessageCompress.decompress_message_data(payload) uncompressedLen = len(payload) else: l = len(payload) @@ -1658,7 +1658,7 @@ class WebSocketProtocol(object): # handle end of compressed message # if self._isMessageCompressed: - self._perMessageCompress.endDecompressMessage() + self._perMessageCompress.end_decompress_message() # verify UTF8 has actually ended # @@ -1802,7 +1802,7 @@ class WebSocketProtocol(object): # mask frame payload # if l > 0 and self.applyMask: - masker = createXorMasker(mask, l) + masker = create_xor_masker(mask, l) plm = masker.process(pl) else: plm = pl @@ -1978,7 +1978,7 @@ class WebSocketProtocol(object): # if self._perMessageCompress is not None and not doNotCompress: self.send_compressed = True - self._perMessageCompress.startCompressMessage() + self._perMessageCompress.start_compress_message() else: self.send_compressed = False @@ -2019,7 +2019,7 @@ class WebSocketProtocol(object): # payload masker # if self.send_message_frame_mask and length > 0 and self.applyMask: - self.send_message_frame_masker = createXorMasker(self.send_message_frame_mask, length) + self.send_message_frame_masker = create_xor_masker(self.send_message_frame_mask, length) else: self.send_message_frame_masker = XorMaskerNull() @@ -2128,7 +2128,7 @@ class WebSocketProtocol(object): # raise Exception("WebSocketProtocol.endMessage invalid in current sending state [%d]" % self.send_state) if self.send_compressed: - payload = self._perMessageCompress.endCompressMessage() + payload = self._perMessageCompress.end_compress_message() self.trafficStats.outgoingOctetsWebSocketLevel += len(payload) else: # send continuation frame with empty payload and FIN set to end message @@ -2146,7 +2146,7 @@ class WebSocketProtocol(object): if self.send_compressed: self.trafficStats.outgoingOctetsAppLevel += len(payload) - payload = self._perMessageCompress.compressMessageData(payload) + payload = self._perMessageCompress.compress_message_data(payload) self.beginMessageFrame(len(payload)) self.sendMessageFrameData(payload, sync) @@ -2182,12 +2182,12 @@ class WebSocketProtocol(object): if self._perMessageCompress is not None and not doNotCompress: sendCompressed = True - self._perMessageCompress.startCompressMessage() + self._perMessageCompress.start_compress_message() self.trafficStats.outgoingOctetsAppLevel += len(payload) - payload1 = self._perMessageCompress.compressMessageData(payload) - payload2 = self._perMessageCompress.endCompressMessage() + payload1 = self._perMessageCompress.compress_message_data(payload) + payload2 = self._perMessageCompress.end_compress_message() payload = b''.join([payload1, payload2]) self.trafficStats.outgoingOctetsWebSocketLevel += len(payload) @@ -2318,7 +2318,7 @@ class PreparedMessage(object): if l == 0: plm = payload else: - plm = createXorMasker(mask, l).process(payload) + plm = create_xor_masker(mask, l).process(payload) else: b1 = 0 mask = b'' @@ -2886,9 +2886,9 @@ class WebSocketServerProtocol(WebSocketProtocol): accept = self.perMessageCompressionAccept(pmceOffers) if accept is not None: PMCE = PERMESSAGE_COMPRESSION_EXTENSION[accept.EXTENSION_NAME] - self._perMessageCompress = PMCE['PMCE'].createFromOfferAccept(self.factory.isServer, accept) + self._perMessageCompress = PMCE['PMCE'].create_from_offer_accept(self.factory.isServer, accept) self.websocket_extensions_in_use.append(self._perMessageCompress) - extensionResponse.append(accept.getExtensionString()) + extensionResponse.append(accept.get_extension_string()) else: self.log.debug( "client request permessage-compress extension, but we did " @@ -3571,7 +3571,7 @@ class WebSocketClientProtocol(WebSocketProtocol): # permessage-compress offers # for offer in self.perMessageCompressionOffers: - extensions.append(offer.getExtensionString()) + extensions.append(offer.get_extension_string()) if len(extensions) > 0: request += "Sec-WebSocket-Extensions: %s\x0d\x0a" % ', '.join(extensions) @@ -3728,7 +3728,7 @@ class WebSocketClientProtocol(WebSocketProtocol): if accept is None: return self.failHandshake("WebSocket permessage-compress extension response from server denied by client") - self._perMessageCompress = PMCE['PMCE'].createFromResponseAccept(self.factory.isServer, accept) + self._perMessageCompress = PMCE['PMCE'].create_from_response_accept(self.factory.isServer, accept) self.websocket_extensions_in_use.append(self._perMessageCompress) diff --git a/autobahn/websocket/utf8validator.py b/autobahn/websocket/utf8validator.py index 5828fd67..3355c636 100644 --- a/autobahn/websocket/utf8validator.py +++ b/autobahn/websocket/utf8validator.py @@ -54,17 +54,15 @@ UTF8_REJECT = 1 # use Cython implementation of UTF8 validator if available -# try: from wsaccel.utf8validator import Utf8Validator except ImportError: - # + # Fallback to pure Python implementation - also for PyPy. # # Do NOT touch this code unless you know what you are doing! # https://github.com/oberstet/scratchbox/tree/master/python/utf8 - # import six @@ -83,7 +81,16 @@ except ImportError: Bjoern Hoehrmann (http://bjoern.hoehrmann.de/utf-8/decoder/dfa/). """ + __slots__ = ( + '_codepoint', + '_state', + '_index', + ) + def __init__(self): + self._codepoint = None + self._state = None + self._index = None self.reset() def decode(self, b): @@ -98,20 +105,20 @@ except ImportError: Returns some other positive integer when more octets need to be eaten. """ tt = UTF8VALIDATOR_DFA_S[b] - if self.state != UTF8_ACCEPT: - self.codepoint = (b & 0x3f) | (self.codepoint << 6) + if self._state != UTF8_ACCEPT: + self._codepoint = (b & 0x3f) | (self._codepoint << 6) else: - self.codepoint = (0xff >> tt) & b - self.state = UTF8VALIDATOR_DFA_S[256 + self.state * 16 + tt] - return self.state + self._codepoint = (0xff >> tt) & b + self._state = UTF8VALIDATOR_DFA_S[256 + self._state * 16 + tt] + return self._state def reset(self): """ Reset validator to start new incremental UTF-8 decode/validation. """ - self.state = UTF8_ACCEPT # the empty string is valid UTF8 - self.codepoint = 0 - self.i = 0 + self._state = UTF8_ACCEPT # the empty string is valid UTF8 + self._codepoint = 0 + self._index = 0 def validate(self, ba): """ @@ -132,18 +139,18 @@ except ImportError: # l = len(ba) i = 0 - state = self.state + state = self._state while i < l: # optimized version of decode(), since we are not interested in actual code points state = UTF8VALIDATOR_DFA_S[256 + (state << 4) + UTF8VALIDATOR_DFA_S[ba[i]]] if state == UTF8_REJECT: - self.state = state - self.i += i - return False, False, i, self.i + self._state = state + self._index += i + return False, False, i, self._index i += 1 - self.state = state - self.i += l - return True, state == UTF8_ACCEPT, l, self.i + self._state = state + self._index += l + return True, state == UTF8_ACCEPT, l, self._index else: @@ -158,7 +165,16 @@ except ImportError: Bjoern Hoehrmann (http://bjoern.hoehrmann.de/utf-8/decoder/dfa/). """ + __slots__ = ( + '_codepoint', + '_state', + '_index', + ) + def __init__(self): + self._codepoint = None + self._state = None + self._index = None self.reset() def decode(self, b): @@ -173,20 +189,20 @@ except ImportError: Returns some other positive integer when more octets need to be eaten. """ tt = ord(UTF8VALIDATOR_DFA_S[b]) - if self.state != UTF8_ACCEPT: - self.codepoint = (b & 0x3f) | (self.codepoint << 6) + if self._state != UTF8_ACCEPT: + self._codepoint = (b & 0x3f) | (self._codepoint << 6) else: - self.codepoint = (0xff >> tt) & b - self.state = ord(UTF8VALIDATOR_DFA_S[256 + self.state * 16 + tt]) - return self.state + self._codepoint = (0xff >> tt) & b + self._state = ord(UTF8VALIDATOR_DFA_S[256 + self._state * 16 + tt]) + return self._state def reset(self): """ Reset validator to start new incremental UTF-8 decode/validation. """ - self.state = UTF8_ACCEPT # the empty string is valid UTF8 - self.codepoint = 0 - self.i = 0 + self._state = UTF8_ACCEPT # the empty string is valid UTF8 + self._codepoint = 0 + self._index = 0 def validate(self, ba): """ @@ -207,15 +223,15 @@ except ImportError: # l = len(ba) i = 0 - state = self.state + state = self._state while i < l: # optimized version of decode(), since we are not interested in actual code points state = ord(UTF8VALIDATOR_DFA_S[256 + (state << 4) + ord(UTF8VALIDATOR_DFA_S[ord(ba[i])])]) if state == UTF8_REJECT: - self.state = state - self.i += i - return False, False, i, self.i + self._state = state + self._index += i + return False, False, i, self._index i += 1 - self.state = state - self.i += l - return True, state == UTF8_ACCEPT, l, self.i + self._state = state + self._index += l + return True, state == UTF8_ACCEPT, l, self._index diff --git a/autobahn/websocket/xormasker.py b/autobahn/websocket/xormasker.py index d52ffee5..8825594e 100644 --- a/autobahn/websocket/xormasker.py +++ b/autobahn/websocket/xormasker.py @@ -26,17 +26,21 @@ import six - -# use Cython implementation of XorMasker validator if available -## try: - from wsaccel.xormask import XorMaskerNull, createXorMasker + # use Cython implementation of XorMasker validator if available + + from wsaccel.xormask import XorMaskerNull + # noinspection PyUnresolvedReferences + from wsaccel.xormask import createXorMasker + create_xor_masker = createXorMasker except ImportError: - # fallback to pure Python implementation + + # fallback to pure Python implementation (this is faster on PyPy than above!) # http://stackoverflow.com/questions/15014310/python3-xrange-lack-hurts try: + # noinspection PyUnresolvedReferences xrange except NameError: # Python 3 @@ -47,39 +51,43 @@ except ImportError: class XorMaskerNull(object): + __slots__ = ('_ptr',) + # noinspection PyUnusedLocal def __init__(self, mask=None): - self.ptr = 0 + self._ptr = 0 def pointer(self): - return self.ptr + return self._ptr def reset(self): - self.ptr = 0 + self._ptr = 0 def process(self, data): - self.ptr += len(data) + self._ptr += len(data) return data class XorMaskerSimple(object): + __slots__ = ('_ptr', '_msk') + def __init__(self, mask): assert len(mask) == 4 - self.ptr = 0 - self.msk = array('B', mask) + self._ptr = 0 + self._msk = array('B', mask) def pointer(self): - return self.ptr + return self._ptr def reset(self): - self.ptr = 0 + self._ptr = 0 def process(self, data): dlen = len(data) payload = array('B', data) for k in xrange(dlen): - payload[k] ^= self.msk[self.ptr & 3] - self.ptr += 1 + payload[k] ^= self._msk[self._ptr & 3] + self._ptr += 1 if six.PY3: return payload.tobytes() else: @@ -87,42 +95,44 @@ except ImportError: class XorMaskerShifted1(object): + __slots__ = ('_ptr', '_mskarray') + def __init__(self, mask): assert len(mask) == 4 - self.ptr = 0 - self.mskarray = [array('B'), array('B'), array('B'), array('B')] + self._ptr = 0 + self._mskarray = [array('B'), array('B'), array('B'), array('B')] if six.PY3: for j in xrange(4): - self.mskarray[0].append(mask[j & 3]) - self.mskarray[1].append(mask[(j + 1) & 3]) - self.mskarray[2].append(mask[(j + 2) & 3]) - self.mskarray[3].append(mask[(j + 3) & 3]) + self._mskarray[0].append(mask[j & 3]) + self._mskarray[1].append(mask[(j + 1) & 3]) + self._mskarray[2].append(mask[(j + 2) & 3]) + self._mskarray[3].append(mask[(j + 3) & 3]) else: for j in xrange(4): - self.mskarray[0].append(ord(mask[j & 3])) - self.mskarray[1].append(ord(mask[(j + 1) & 3])) - self.mskarray[2].append(ord(mask[(j + 2) & 3])) - self.mskarray[3].append(ord(mask[(j + 3) & 3])) + self._mskarray[0].append(ord(mask[j & 3])) + self._mskarray[1].append(ord(mask[(j + 1) & 3])) + self._mskarray[2].append(ord(mask[(j + 2) & 3])) + self._mskarray[3].append(ord(mask[(j + 3) & 3])) def pointer(self): - return self.ptr + return self._ptr def reset(self): - self.ptr = 0 + self._ptr = 0 def process(self, data): dlen = len(data) payload = array('B', data) - msk = self.mskarray[self.ptr & 3] + msk = self._mskarray[self._ptr & 3] for k in xrange(dlen): payload[k] ^= msk[k & 3] - self.ptr += dlen + self._ptr += dlen if six.PY3: return payload.tobytes() else: return payload.tostring() - def createXorMasker(mask, length=None): + def create_xor_masker(mask, length=None): if length is None or length < 128: return XorMaskerSimple(mask) else: