Skip to content

Commit

Permalink
Modifications to support Python 3.
Browse files Browse the repository at this point in the history
Tested on Python 2.6, 2.7, 3.3, 3.4, 3.5
  • Loading branch information
hydratk committed Sep 1, 2016
1 parent b6b13a7 commit 75c5692
Show file tree
Hide file tree
Showing 22 changed files with 395 additions and 347 deletions.
5 changes: 1 addition & 4 deletions src/core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ def read(filename):
return open(os.path.join(os.path.dirname(__file__), filename)).read()

if sys.version_info[:2] < (2, 6):
print 'stompest requires Python version 2.6 or later (%s detected).' % '.'.join(sys.version_info[:2])
sys.exit(-1)
if sys.version_info[:2] >= (3, 0):
print 'stompest is not yet compatible with Python 3 (%s detected).' % '.'.join(sys.version_info[:2])
print('stompest requires Python version 2.6 or later (%s detected).' % '.'.join(sys.version_info[:2]))
sys.exit(-1)

setup(
Expand Down
12 changes: 6 additions & 6 deletions src/core/stompest/protocol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"""
# TODO: STOMP 1.1 - deal with repeated headers -> http://stomp.github.com/stomp-specification-1.1.html#Repeated_Header_Entries

import commands
from failover import StompFailoverTransport, StompFailoverUri
from frame import StompFrame
from parser import StompParser
from spec import StompSpec
from session import StompSession
import stompest.protocol.commands
from stompest.protocol.failover import StompFailoverTransport, StompFailoverUri
from stompest.protocol.frame import StompFrame
from stompest.protocol.parser import StompParser
from stompest.protocol.spec import StompSpec
from stompest.protocol.session import StompSession
14 changes: 9 additions & 5 deletions src/core/stompest/protocol/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@
.. seealso :: Specification of STOMP protocols `1.0 <http://stomp.github.com//stomp-specification-1.0.html>`_ and `1.1 <http://stomp.github.com//stomp-specification-1.1.html>`_, your favorite broker's documentation for additional STOMP headers.
"""
from sys import version_info
from stompest.error import StompProtocolError

from .frame import StompFrame, StompHeartBeat
from .spec import StompSpec
from stompest.protocol.frame import StompFrame, StompHeartBeat
from stompest.protocol.spec import StompSpec

# outgoing frames

Expand Down Expand Up @@ -120,7 +121,10 @@ def subscribe(destination, headers, receipt=None, version=None):
if (version != StompSpec.VERSION_1_0):
raise
token = (StompSpec.DESTINATION_HEADER, destination) if (subscription is None) else (StompSpec.ID_HEADER, subscription)
return frame, tuple(map(unicode, token))
if version_info[0] == 2:
return frame, tuple(map(unicode, token))
else:
return frame, tuple(map(str, token))

def unsubscribe(token, receipt=None, version=None):
"""Create an **UNSUBSCRIBE** frame.
Expand Down Expand Up @@ -301,12 +305,12 @@ def _ackHeaders(frame, transactions):
else:
if transaction in set(transactions or []):
keys[StompSpec.TRANSACTION_HEADER] = StompSpec.TRANSACTION_HEADER
return dict((keys[key], value) for (key, value) in frame.headers.iteritems() if key in keys)
return dict((keys[key], value) for (key, value) in frame.headers.items() if key in keys)

def _addReceiptHeader(frame, receipt):
if not receipt:
return
if not isinstance(receipt, basestring):
if not isinstance(receipt, str):
raise StompProtocolError('Invalid receipt (not a string): %s' % repr(receipt))
frame.headers[StompSpec.RECEIPT_HEADER] = str(receipt)

Expand Down
18 changes: 9 additions & 9 deletions src/core/stompest/protocol/failover.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ def isLocalHost(cls, host):
socket.gethostbyname,
socket.getfqdn
):
try:
if host == alternative(hostName):
return True
except socket.gaierror:
pass
try:
if host == alternative(hostName):
return True
except socket.gaierror:
pass
return False

def _brokers(self):
Expand Down Expand Up @@ -177,15 +177,15 @@ def _parse(self, uri):

try:
self._setOptions(options)
except Exception, msg:
except Exception as msg:
raise ValueError('invalid options: %s' % msg)

try:
self._setBrokers(uri)
except Exception, msg:
except Exception as msg:
raise ValueError('invalid broker(s): %s' % msg)

except ValueError, msg:
except ValueError as msg:
raise ValueError('invalid uri: %s [%s]' % (self.uri, msg))

def _setBrokers(self, uri):
Expand All @@ -197,7 +197,7 @@ def _setBrokers(self, uri):
self.brokers = brokers

def _setOptions(self, options=None):
_options = dict((k, o.default) for (k, o) in self._SUPPORTED_OPTIONS.iteritems())
_options = dict((k, o.default) for (k, o) in self._SUPPORTED_OPTIONS.items())
if options:
_options.update((k, self._SUPPORTED_OPTIONS[k].parser(v)) for (k, _, v) in (o.partition('=') for o in options.split(',')))
self.options = _options
17 changes: 11 additions & 6 deletions src/core/stompest/protocol/frame.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .spec import StompSpec
from .util import escape
from stompest.protocol.spec import StompSpec
from stompest.protocol.util import escape
from sys import version_info

class StompFrame(object):
"""This object represents a STOMP frame.
Expand Down Expand Up @@ -82,9 +83,13 @@ def __repr__(self):

def __str__(self):
"""Render the wire-level representation of a STOMP frame."""
headers = sorted(self.headers.iteritems()) if self.rawHeaders is None else self.rawHeaders
headers = ''.join('%s:%s%s' % (self._encode(self._escape(unicode(key))), self._encode(self._escape(unicode(value))), StompSpec.LINE_DELIMITER) for (key, value) in headers)
return StompSpec.LINE_DELIMITER.join([self._encode(unicode(self.command)), headers, '%s%s' % (self.body, StompSpec.FRAME_DELIMITER)])
headers = sorted(self.headers.items()) if self.rawHeaders is None else self.rawHeaders
if version_info[0] == 2:
headers = ''.join('%s:%s%s' % (self._encode(self._escape(unicode(key))), self._encode(self._escape(unicode(value))), StompSpec.LINE_DELIMITER) for (key, value) in headers)
return StompSpec.LINE_DELIMITER.join([self._encode(unicode(self.command)), headers, '%s%s' % (self.body, StompSpec.FRAME_DELIMITER)])
else:
headers = ''.join('%s:%s%s' % (self._encode(self._escape(str(key))), self._encode(self._escape(str(value))), StompSpec.LINE_DELIMITER) for (key, value) in headers)
return StompSpec.LINE_DELIMITER.join([self._encode(str(self.command)), headers, '%s%s' % (self.body, StompSpec.FRAME_DELIMITER)])

def info(self):
"""Produce a log-friendly representation of the frame (show only non-trivial content, and truncate the message to INFO_LENGTH characters)."""
Expand All @@ -106,7 +111,7 @@ def version(self, value):
self._version = StompSpec.version(value)

def _encode(self, text):
return StompSpec.CODECS[self.version].encode(text)[0]
return StompSpec.CODECS[self.version].encode(text)[0] if version_info[0] == 2 else StompSpec.CODECS[self.version].encode(text)[0].decode()

def _escape(self, text):
return escape(self.version)(self.command, text)
Expand Down
27 changes: 22 additions & 5 deletions src/core/stompest/protocol/parser.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import collections
import cStringIO
from sys import version_info

try:
from cStringIO import StringIO
except ImportError:
from io import StringIO

from stompest.error import StompFrameError

from .frame import StompFrame, StompHeartBeat
from .spec import StompSpec
from .util import unescape
from stompest.protocol.frame import StompFrame, StompHeartBeat
from stompest.protocol.spec import StompSpec
from stompest.protocol.util import unescape

class StompParser(object):
"""This is a parser for a wire-level byte-stream of STOMP frames.
Expand Down Expand Up @@ -64,6 +69,8 @@ def add(self, data):
:param data: An iterable of characters. If any character evaluates to :obj:`False`, that stream will no longer be consumed.
"""
if version_info[0] == 3 and data.__class__.__name__ not in ['str', 'generator']:
data = data.decode()
for character in data:
if not character:
return
Expand All @@ -76,7 +83,7 @@ def reset(self):
self._next()

def _flush(self):
self._buffer = cStringIO.StringIO()
self._buffer = StringIO()

def _next(self):
self._frame = None
Expand All @@ -95,6 +102,8 @@ def _transition(self, state):
self.parse = self._parsers[state]

def _parseHeartBeat(self, character):
if version_info[0] == 3 and character.__class__.__name__ != 'str':
character = chr(character)
if character != StompSpec.LINE_DELIMITER:
self._transition('command')
self.parse(character)
Expand All @@ -105,6 +114,8 @@ def _parseHeartBeat(self, character):
self._append()

def _parseCommand(self, character):
if version_info[0] == 3 and character.__class__.__name__ != 'str':
character = chr(character)
if character != StompSpec.LINE_DELIMITER:
self._buffer.write(character)
return
Expand All @@ -115,6 +126,8 @@ def _parseCommand(self, character):
self._transition('headers')

def _parseHeader(self, character):
if version_info[0] == 3 and character.__class__.__name__ != 'str':
character = chr(character)
if character != StompSpec.LINE_DELIMITER:
self._buffer.write(character)
return
Expand All @@ -132,6 +145,8 @@ def _parseHeader(self, character):
self._transition('body')

def _parseBody(self, character):
if version_info[0] == 3 and character.__class__.__name__ != 'str':
character = chr(character)
self._read += 1
if (self._read <= self._length) or (character != StompSpec.FRAME_DELIMITER):
self._buffer.write(character)
Expand All @@ -147,6 +162,8 @@ def _raise(self, message):
raise StompFrameError(message)

def _decode(self, data):
if version_info[0] == 3:
data = data.encode()
text = StompSpec.CODECS[self.version].decode(data)[0]
stripLineDelimiter = StompSpec.STRIP_LINE_DELIMITER.get(self.version, '')
if stripLineDelimiter and text.endswith(stripLineDelimiter):
Expand Down
Loading

0 comments on commit 75c5692

Please sign in to comment.