Permalink
Browse files

Remove text_socket, fix Python 3 compat issues. [Vinay Sajip]

  • Loading branch information...
mnaberez committed Dec 17, 2017
1 parent 71c7924 commit ffbd5d27461166793da55ff45954b1702476d556
View
@@ -6,6 +6,7 @@
*.pyc
*.pyo
*.swp
*.pss
.DS_Store
.coverage
.eggs/
View
@@ -3,6 +3,7 @@
from supervisor.compat import xmlrpclib
from supervisor.compat import long
from supervisor.compat import as_string
from supervisor.xmlrpc import SupervisorTransport
from supervisor.events import ProcessCommunicationEvent
@@ -58,7 +59,7 @@ def wait(self, stdin=sys.stdin, stdout=sys.stdout):
return headers, payload
def ready(self, stdout=sys.stdout):
stdout.write(PEventListenerDispatcher.READY_FOR_EVENTS_TOKEN)
stdout.write(as_string(PEventListenerDispatcher.READY_FOR_EVENTS_TOKEN))
stdout.flush()
def ok(self, stdout=sys.stdout):
@@ -69,7 +70,7 @@ def fail(self, stdout=sys.stdout):
def send(self, data, stdout=sys.stdout):
resultlen = len(data)
result = '%s%s\n%s' % (PEventListenerDispatcher.RESULT_TOKEN_START,
result = '%s%s\n%s' % (as_string(PEventListenerDispatcher.RESULT_TOKEN_START),
str(resultlen),
data)
stdout.write(result)
View
@@ -14,6 +14,10 @@ def __init__(self, string, encoding, errors):
def as_bytes(s): return s if isinstance(s,bytes) else s.encode('utf8')
def as_string(s): return s if isinstance(s,str) else s.decode('utf8')
def is_text_stream(stream):
import _io
return isinstance(stream, _io._TextIOBase)
else: # pragma: no cover
long = long
raw_input = raw_input
@@ -22,6 +26,18 @@ def as_string(s): return s if isinstance(s,str) else s.decode('utf8')
def as_bytes(s): return s if isinstance(s, str) else s.encode('utf-8')
def as_string(s): return s if isinstance(s, unicode) else s.decode('utf-8')
def is_text_stream(stream):
# TODO sort out for Python 2.4, 2.5 and 2.6 when a stream is
# opened using plain open() or codecs.open() rather than io.open()
if isinstance(stream, file):
return 'b' not in stream.mode
try:
import _io
return isinstance(stream, _io._TextIOBase)
except ImportError:
import io
return isinstance(stream, io.TextIOWrapper)
def total_ordering(cls): # pragma: no cover
"""Class decorator that fills in missing ordering methods"""
convert = {
View
@@ -2,6 +2,7 @@
import errno
from supervisor.medusa.asyncore_25 import compact_traceback
from supervisor.compat import as_string
from supervisor.events import notify
from supervisor.events import EventRejectedEvent
from supervisor.events import ProcessLogStderrEvent
@@ -83,7 +84,7 @@ class POutputDispatcher(PDispatcher):
mainlog = None # the process' "normal" logger
capturelog = None # the logger while we're in capturemode
childlog = None # the current logger (event or main)
output_buffer = '' # data waiting to be logged
output_buffer = b'' # data waiting to be logged
def __init__(self, process, event_type, fd):
"""
@@ -171,10 +172,17 @@ def _log(self, data):
if self.childlog:
self.childlog.info(data)
if self.log_to_mainlog:
if not isinstance(data, bytes):
text = data
else:
try:
text = data.decode('utf-8')
except UnicodeDecodeError:
text = 'Undecodable: %r' % data
msg = '%(name)r %(channel)s output:\n%(data)s'
config.options.logger.log(
self.mainlog_level, msg, name=config.name,
channel=self.channel, data=data)
channel=self.channel, data=text)
if self.channel == 'stdout':
if self.stdout_events_enabled:
notify(
@@ -192,7 +200,7 @@ def record_output(self):
if self.capturelog is None:
# shortcut trying to find capture data
data = self.output_buffer
self.output_buffer = ''
self.output_buffer = b''
self._log(data)
return
@@ -205,7 +213,7 @@ def record_output(self):
return # not enough data
data = self.output_buffer
self.output_buffer = ''
self.output_buffer = b''
try:
before, after = data.split(token, 1)
@@ -270,10 +278,10 @@ class PEventListenerDispatcher(PDispatcher):
""" An output dispatcher that monitors and changes a process'
listener_state """
childlog = None # the logger
state_buffer = '' # data waiting to be reviewed for state changes
state_buffer = b'' # data waiting to be reviewed for state changes
READY_FOR_EVENTS_TOKEN = 'READY\n'
RESULT_TOKEN_START = 'RESULT '
READY_FOR_EVENTS_TOKEN = b'READY\n'
RESULT_TOKEN_START = b'RESULT '
READY_FOR_EVENTS_LEN = len(READY_FOR_EVENTS_TOKEN)
RESULT_TOKEN_START_LEN = len(RESULT_TOKEN_START)
@@ -283,7 +291,7 @@ def __init__(self, process, channel, fd):
# "busy" state that implies we're awaiting a READY_FOR_EVENTS_TOKEN
self.process.listener_state = EventListenerStates.ACKNOWLEDGED
self.process.event = None
self.result = ''
self.result = b''
self.resultlen = None
logfile = getattr(process.config, '%s_logfile' % channel)
@@ -352,7 +360,7 @@ def handle_listener_state_change(self):
if state == EventListenerStates.UNKNOWN:
# this is a fatal state
self.state_buffer = ''
self.state_buffer = b''
return
if state == EventListenerStates.ACKNOWLEDGED:
@@ -366,7 +374,7 @@ def handle_listener_state_change(self):
process.event = None
else:
self._change_listener_state(EventListenerStates.UNKNOWN)
self.state_buffer = ''
self.state_buffer = b''
process.event = None
if self.state_buffer:
# keep going til its too short
@@ -377,14 +385,14 @@ def handle_listener_state_change(self):
elif state == EventListenerStates.READY:
# the process sent some spurious data, be strict about it
self._change_listener_state(EventListenerStates.UNKNOWN)
self.state_buffer = ''
self.state_buffer = b''
process.event = None
return
elif state == EventListenerStates.BUSY:
if self.resultlen is None:
# we haven't begun gathering result data yet
pos = data.find('\n')
pos = data.find(b'\n')
if pos == -1:
# we can't make a determination yet, we dont have a full
# results line
@@ -396,11 +404,15 @@ def handle_listener_state_change(self):
try:
self.resultlen = int(resultlen)
except ValueError:
try:
result_line = as_string(result_line)
except UnicodeDecodeError:
result_line = 'Undecodable: %r' % result_line
process.config.options.logger.warn(
'%s: bad result line: %r' % (procname, result_line)
'%s: bad result line: \'%s\'' % (procname, result_line)
)
self._change_listener_state(EventListenerStates.UNKNOWN)
self.state_buffer = ''
self.state_buffer = b''
notify(EventRejectedEvent(process, process.event))
process.event = None
return
@@ -416,7 +428,7 @@ def handle_listener_state_change(self):
if not needed:
self.handle_result(self.result)
self.process.event = None
self.result = ''
self.result = b''
self.resultlen = None
if self.state_buffer:
@@ -465,7 +477,7 @@ class PInputDispatcher(PDispatcher):
def __init__(self, process, channel, fd):
PDispatcher.__init__(self, process, channel, fd)
self.input_buffer = ''
self.input_buffer = b''
def writable(self):
if self.input_buffer and not self.closed:
@@ -487,25 +499,25 @@ def handle_write_event(self):
self.flush()
except OSError as why:
if why.args[0] == errno.EPIPE:
self.input_buffer = ''
self.input_buffer = b''
self.close()
else:
raise
ANSI_ESCAPE_BEGIN = '\x1b['
ANSI_TERMINATORS = ('H', 'f', 'A', 'B', 'C', 'D', 'R', 's', 'u', 'J',
'K', 'h', 'l', 'p', 'm')
ANSI_ESCAPE_BEGIN = b'\x1b['
ANSI_TERMINATORS = (b'H', b'f', b'A', b'B', b'C', b'D', b'R', b's', b'u', b'J',
b'K', b'h', b'l', b'p', b'm')
def stripEscapes(s):
"""
Remove all ANSI color escapes from the given string.
"""
result = ''
result = b''
show = 1
i = 0
L = len(s)
while i < L:
if show == 0 and s[i] in ANSI_TERMINATORS:
if show == 0 and s[i:i + 1] in ANSI_TERMINATORS:
show = 1
elif show:
n = s.find(ANSI_ESCAPE_BEGIN, i)
@@ -523,5 +535,5 @@ class RejectEvent(Exception):
to reject an event """
def default_handler(event, response):
if response != 'OK':
if response != b'OK':
raise RejectEvent(response)
View
@@ -1,10 +1,11 @@
from supervisor.states import getProcessStateDescription
from supervisor.compat import as_string
callbacks = []
def subscribe(type, callback):
callbacks.append((type, callback))
def notify(event):
for type, callback in callbacks:
if isinstance(event, type):
@@ -25,16 +26,22 @@ def __init__(self, process, pid, data):
self.pid = pid
self.data = data
def __str__(self):
def payload(self):
groupname = ''
if self.process.group is not None:
groupname = self.process.group.config.name
return 'processname:%s groupname:%s pid:%s channel:%s\n%s' % (
self.process.config.name,
groupname,
self.pid,
self.channel,
self.data)
try:
data = as_string(self.data)
except UnicodeDecodeError:
data = 'Undecodable: %r' % self.data
# On Python 2, stuff needs to be in Unicode before invoking the
# % operator, otherwise implicit encodings to ASCII can cause
# failures
fmt = as_string('processname:%s groupname:%s pid:%s channel:%s\n%s')
result = fmt % (as_string(self.process.config.name),
as_string(groupname), self.pid,
as_string(self.channel), data)
return result
class ProcessLogStdoutEvent(ProcessLogEvent):
channel = 'stdout'
@@ -45,23 +52,27 @@ class ProcessLogStderrEvent(ProcessLogEvent):
class ProcessCommunicationEvent(Event):
""" Abstract """
# event mode tokens
BEGIN_TOKEN = '<!--XSUPERVISOR:BEGIN-->'
END_TOKEN = '<!--XSUPERVISOR:END-->'
BEGIN_TOKEN = b'<!--XSUPERVISOR:BEGIN-->'
END_TOKEN = b'<!--XSUPERVISOR:END-->'
def __init__(self, process, pid, data):
self.process = process
self.pid = pid
self.data = data
def __str__(self):
def payload(self):
groupname = ''
if self.process.group is not None:
groupname = self.process.group.config.name
try:
data = as_string(self.data)
except UnicodeDecodeError:
data = 'Undecodable: %r' % self.data
return 'processname:%s groupname:%s pid:%s\n%s' % (
self.process.config.name,
groupname,
self.pid,
self.data)
data)
class ProcessCommunicationStdoutEvent(ProcessCommunicationEvent):
channel = 'stdout'
@@ -74,12 +85,12 @@ def __init__(self, type, data):
self.type = type
self.data = data
def __str__(self):
def payload(self):
return 'type:%s\n%s' % (self.type, self.data)
class SupervisorStateChangeEvent(Event):
""" Abstract class """
def __str__(self):
def payload(self):
return ''
class SupervisorRunningEvent(SupervisorStateChangeEvent):
@@ -88,7 +99,7 @@ class SupervisorRunningEvent(SupervisorStateChangeEvent):
class SupervisorStoppingEvent(SupervisorStateChangeEvent):
pass
class EventRejectedEvent: # purposely does not subclass Event
class EventRejectedEvent: # purposely does not subclass Event
def __init__(self, process, event):
self.process = process
self.event = event
@@ -105,7 +116,7 @@ def __init__(self, process, from_state, expected=True):
# us, we stash the values at the time the event was sent
self.extra_values = self.get_extra_values()
def __str__(self):
def payload(self):
groupname = ''
if self.process.group is not None:
groupname = self.process.group.config.name
@@ -153,7 +164,8 @@ def get_extra_values(self):
class ProcessGroupEvent(Event):
def __init__(self, group):
self.group = group
def __str__(self):
def payload(self):
return 'groupname:%s\n' % self.group
class ProcessGroupAddedEvent(ProcessGroupEvent):
@@ -168,7 +180,7 @@ def __init__(self, when, supervisord):
self.when = when
self.supervisord = supervisord
def __str__(self):
def payload(self):
return 'when:%s' % self.when
class Tick5Event(TickEvent):
@@ -198,7 +210,7 @@ class EventTypes:
PROCESS_COMMUNICATION_STDERR = ProcessCommunicationStderrEvent
PROCESS_LOG = ProcessLogEvent
PROCESS_LOG_STDOUT = ProcessLogStdoutEvent
PROCESS_LOG_STDERR = ProcessLogStderrEvent
PROCESS_LOG_STDERR = ProcessLogStderrEvent
REMOTE_COMMUNICATION = RemoteCommunicationEvent
SUPERVISOR_STATE_CHANGE = SupervisorStateChangeEvent # abstract
SUPERVISOR_STATE_CHANGE_RUNNING = SupervisorRunningEvent
Oops, something went wrong.

0 comments on commit ffbd5d2

Please sign in to comment.