Switch to tabs for indentation.
Instead of a mix of 2- and 4-space tabs just use actual tabs. ;-P
This commit is contained in:
+161
-161
@@ -48,18 +48,18 @@ GREEN = 70, 200, 70
|
||||
|
||||
|
||||
MOUSE_EVENTS = frozenset({
|
||||
pygame.MOUSEMOTION,
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.MOUSEBUTTONUP
|
||||
})
|
||||
pygame.MOUSEMOTION,
|
||||
pygame.MOUSEBUTTONDOWN,
|
||||
pygame.MOUSEBUTTONUP
|
||||
})
|
||||
'PyGame mouse events.'
|
||||
|
||||
ARROW_KEYS = frozenset({
|
||||
pygame.K_UP,
|
||||
pygame.K_DOWN,
|
||||
pygame.K_LEFT,
|
||||
pygame.K_RIGHT
|
||||
})
|
||||
pygame.K_UP,
|
||||
pygame.K_DOWN,
|
||||
pygame.K_LEFT,
|
||||
pygame.K_RIGHT
|
||||
})
|
||||
'PyGame arrow key events.'
|
||||
|
||||
|
||||
@@ -82,201 +82,201 @@ SUCCESS = 1
|
||||
|
||||
|
||||
class Message(object):
|
||||
'''Message base class. Contains ``sender`` field.'''
|
||||
def __init__(self, sender):
|
||||
self.sender = sender
|
||||
'''Message base class. Contains ``sender`` field.'''
|
||||
def __init__(self, sender):
|
||||
self.sender = sender
|
||||
|
||||
|
||||
class CommandMessage(Message):
|
||||
'''For commands, adds ``command`` field.'''
|
||||
def __init__(self, sender, command):
|
||||
Message.__init__(self, sender)
|
||||
self.command = command
|
||||
'''For commands, adds ``command`` field.'''
|
||||
def __init__(self, sender, command):
|
||||
Message.__init__(self, sender)
|
||||
self.command = command
|
||||
|
||||
|
||||
class ModifyMessage(Message):
|
||||
'''
|
||||
For when resources are modified, adds ``subject`` and ``details``
|
||||
fields.
|
||||
'''
|
||||
def __init__(self, sender, subject, **details):
|
||||
Message.__init__(self, sender)
|
||||
self.subject = subject
|
||||
self.details = details
|
||||
'''
|
||||
For when resources are modified, adds ``subject`` and ``details``
|
||||
fields.
|
||||
'''
|
||||
def __init__(self, sender, subject, **details):
|
||||
Message.__init__(self, sender)
|
||||
self.subject = subject
|
||||
self.details = details
|
||||
|
||||
|
||||
class OpenMessage(Message):
|
||||
'''
|
||||
For when resources are modified, adds ``name``, content_id``,
|
||||
``status``, and ``traceback`` fields.
|
||||
'''
|
||||
def __init__(self, sender, name):
|
||||
Message.__init__(self, sender)
|
||||
self.name = name
|
||||
self.content_id = self.thing = None
|
||||
self.status = PENDING
|
||||
self.traceback = None
|
||||
'''
|
||||
For when resources are modified, adds ``name``, content_id``,
|
||||
``status``, and ``traceback`` fields.
|
||||
'''
|
||||
def __init__(self, sender, name):
|
||||
Message.__init__(self, sender)
|
||||
self.name = name
|
||||
self.content_id = self.thing = None
|
||||
self.status = PENDING
|
||||
self.traceback = None
|
||||
|
||||
|
||||
class PersistMessage(Message):
|
||||
'''
|
||||
For when resources are modified, adds ``content_id`` and ``details``
|
||||
fields.
|
||||
'''
|
||||
def __init__(self, sender, content_id, **details):
|
||||
Message.__init__(self, sender)
|
||||
self.content_id = content_id
|
||||
self.details = details
|
||||
'''
|
||||
For when resources are modified, adds ``content_id`` and ``details``
|
||||
fields.
|
||||
'''
|
||||
def __init__(self, sender, content_id, **details):
|
||||
Message.__init__(self, sender)
|
||||
self.content_id = content_id
|
||||
self.details = details
|
||||
|
||||
|
||||
class ShutdownMessage(Message):
|
||||
'''Signals that the system is shutting down.'''
|
||||
'''Signals that the system is shutting down.'''
|
||||
|
||||
|
||||
# Joy Interpreter & Context
|
||||
|
||||
|
||||
class World(object):
|
||||
'''
|
||||
This object contains the system context, the stack, dictionary, a
|
||||
reference to the display broadcast method, and the log.
|
||||
'''
|
||||
'''
|
||||
This object contains the system context, the stack, dictionary, a
|
||||
reference to the display broadcast method, and the log.
|
||||
'''
|
||||
|
||||
def __init__(self, stack_id, stack_holder, dictionary, notify, log):
|
||||
self.stack_holder = stack_holder
|
||||
self.dictionary = dictionary
|
||||
self.notify = notify
|
||||
self.stack_id = stack_id
|
||||
self.log = log.lines
|
||||
self.log_id = log.content_id
|
||||
def __init__(self, stack_id, stack_holder, dictionary, notify, log):
|
||||
self.stack_holder = stack_holder
|
||||
self.dictionary = dictionary
|
||||
self.notify = notify
|
||||
self.stack_id = stack_id
|
||||
self.log = log.lines
|
||||
self.log_id = log.content_id
|
||||
|
||||
def handle(self, message):
|
||||
'''
|
||||
Deal with updates to the stack and commands.
|
||||
'''
|
||||
if (isinstance(message, ModifyMessage)
|
||||
and message.subject is self.stack_holder
|
||||
):
|
||||
self._log_lines('', '%s <-' % self.format_stack())
|
||||
if not isinstance(message, CommandMessage):
|
||||
return
|
||||
c, s, d = message.command, self.stack_holder[0], self.dictionary
|
||||
self._log_lines('', '-> %s' % (c,))
|
||||
self.stack_holder[0], _, self.dictionary = run(c, s, d)
|
||||
mm = ModifyMessage(self, self.stack_holder, content_id=self.stack_id)
|
||||
self.notify(mm)
|
||||
def handle(self, message):
|
||||
'''
|
||||
Deal with updates to the stack and commands.
|
||||
'''
|
||||
if (isinstance(message, ModifyMessage)
|
||||
and message.subject is self.stack_holder
|
||||
):
|
||||
self._log_lines('', '%s <-' % self.format_stack())
|
||||
if not isinstance(message, CommandMessage):
|
||||
return
|
||||
c, s, d = message.command, self.stack_holder[0], self.dictionary
|
||||
self._log_lines('', '-> %s' % (c,))
|
||||
self.stack_holder[0], _, self.dictionary = run(c, s, d)
|
||||
mm = ModifyMessage(self, self.stack_holder, content_id=self.stack_id)
|
||||
self.notify(mm)
|
||||
|
||||
def _log_lines(self, *lines):
|
||||
self.log.extend(lines)
|
||||
self.notify(ModifyMessage(self, self.log, content_id=self.log_id))
|
||||
def _log_lines(self, *lines):
|
||||
self.log.extend(lines)
|
||||
self.notify(ModifyMessage(self, self.log, content_id=self.log_id))
|
||||
|
||||
def format_stack(self):
|
||||
try:
|
||||
return stack_to_string(self.stack_holder[0])
|
||||
except:
|
||||
print(format_exc(), file=stderr)
|
||||
return str(self.stack_holder[0])
|
||||
def format_stack(self):
|
||||
try:
|
||||
return stack_to_string(self.stack_holder[0])
|
||||
except:
|
||||
print(format_exc(), file=stderr)
|
||||
return str(self.stack_holder[0])
|
||||
|
||||
|
||||
def push(sender, item, notify, stack_name='stack.pickle'):
|
||||
'''
|
||||
Helper function to push an item onto the system stack with message.
|
||||
'''
|
||||
om = OpenMessage(sender, stack_name)
|
||||
notify(om)
|
||||
if om.status == SUCCESS:
|
||||
om.thing[0] = item, om.thing[0]
|
||||
notify(ModifyMessage(sender, om.thing, content_id=om.content_id))
|
||||
return om.status
|
||||
'''
|
||||
Helper function to push an item onto the system stack with message.
|
||||
'''
|
||||
om = OpenMessage(sender, stack_name)
|
||||
notify(om)
|
||||
if om.status == SUCCESS:
|
||||
om.thing[0] = item, om.thing[0]
|
||||
notify(ModifyMessage(sender, om.thing, content_id=om.content_id))
|
||||
return om.status
|
||||
|
||||
|
||||
def open_viewer_on_string(sender, content, notify):
|
||||
'''
|
||||
Helper function to open a text viewer on a string.
|
||||
Typically used to show tracebacks.
|
||||
'''
|
||||
push(sender, content, notify)
|
||||
notify(CommandMessage(sender, 'good_viewer_location open_viewer'))
|
||||
'''
|
||||
Helper function to open a text viewer on a string.
|
||||
Typically used to show tracebacks.
|
||||
'''
|
||||
push(sender, content, notify)
|
||||
notify(CommandMessage(sender, 'good_viewer_location open_viewer'))
|
||||
|
||||
|
||||
# main loop
|
||||
|
||||
|
||||
class TheLoop(object):
|
||||
'''
|
||||
The main loop manages tasks and the PyGame event queue
|
||||
and framerate clock.
|
||||
'''
|
||||
'''
|
||||
The main loop manages tasks and the PyGame event queue
|
||||
and framerate clock.
|
||||
'''
|
||||
|
||||
FRAME_RATE = 24
|
||||
FRAME_RATE = 24
|
||||
|
||||
def __init__(self, display, clock):
|
||||
self.display = display
|
||||
self.clock = clock
|
||||
self.tasks = {}
|
||||
self.running = False
|
||||
def __init__(self, display, clock):
|
||||
self.display = display
|
||||
self.clock = clock
|
||||
self.tasks = {}
|
||||
self.running = False
|
||||
|
||||
def install_task(self, F, milliseconds):
|
||||
'''
|
||||
Install a task to run every so many milliseconds.
|
||||
'''
|
||||
try:
|
||||
task_event_id = AVAILABLE_TASK_EVENTS.pop()
|
||||
except KeyError:
|
||||
raise RuntimeError('out of task ids')
|
||||
self.tasks[task_event_id] = F
|
||||
pygame.time.set_timer(task_event_id, milliseconds)
|
||||
return task_event_id
|
||||
def install_task(self, F, milliseconds):
|
||||
'''
|
||||
Install a task to run every so many milliseconds.
|
||||
'''
|
||||
try:
|
||||
task_event_id = AVAILABLE_TASK_EVENTS.pop()
|
||||
except KeyError:
|
||||
raise RuntimeError('out of task ids')
|
||||
self.tasks[task_event_id] = F
|
||||
pygame.time.set_timer(task_event_id, milliseconds)
|
||||
return task_event_id
|
||||
|
||||
def remove_task(self, task_event_id):
|
||||
'''
|
||||
Remove an installed task.
|
||||
'''
|
||||
assert task_event_id in self.tasks, repr(task_event_id)
|
||||
pygame.time.set_timer(task_event_id, 0)
|
||||
del self.tasks[task_event_id]
|
||||
AVAILABLE_TASK_EVENTS.add(task_event_id)
|
||||
def remove_task(self, task_event_id):
|
||||
'''
|
||||
Remove an installed task.
|
||||
'''
|
||||
assert task_event_id in self.tasks, repr(task_event_id)
|
||||
pygame.time.set_timer(task_event_id, 0)
|
||||
del self.tasks[task_event_id]
|
||||
AVAILABLE_TASK_EVENTS.add(task_event_id)
|
||||
|
||||
def __del__(self):
|
||||
# Best effort to cancel all running tasks.
|
||||
for task_event_id in self.tasks:
|
||||
pygame.time.set_timer(task_event_id, 0)
|
||||
def __del__(self):
|
||||
# Best effort to cancel all running tasks.
|
||||
for task_event_id in self.tasks:
|
||||
pygame.time.set_timer(task_event_id, 0)
|
||||
|
||||
def run_task(self, task_event_id):
|
||||
'''
|
||||
Give a task its time to shine.
|
||||
'''
|
||||
task = self.tasks[task_event_id]
|
||||
try:
|
||||
task()
|
||||
except:
|
||||
traceback = format_exc()
|
||||
self.remove_task(task_event_id)
|
||||
print(traceback, file=stderr)
|
||||
print('TASK removed due to ERROR', task, file=stderr)
|
||||
open_viewer_on_string(self, traceback, self.display.broadcast)
|
||||
def run_task(self, task_event_id):
|
||||
'''
|
||||
Give a task its time to shine.
|
||||
'''
|
||||
task = self.tasks[task_event_id]
|
||||
try:
|
||||
task()
|
||||
except:
|
||||
traceback = format_exc()
|
||||
self.remove_task(task_event_id)
|
||||
print(traceback, file=stderr)
|
||||
print('TASK removed due to ERROR', task, file=stderr)
|
||||
open_viewer_on_string(self, traceback, self.display.broadcast)
|
||||
|
||||
def loop(self):
|
||||
'''
|
||||
The actual main loop machinery.
|
||||
def loop(self):
|
||||
'''
|
||||
The actual main loop machinery.
|
||||
|
||||
Maintain a ``running`` flag, pump the PyGame event queue and
|
||||
handle the events (dispatching to the display), tick the clock.
|
||||
Maintain a ``running`` flag, pump the PyGame event queue and
|
||||
handle the events (dispatching to the display), tick the clock.
|
||||
|
||||
When the loop is exited (by clicking the window close button or
|
||||
pressing the ``escape`` key) it broadcasts a ``ShutdownMessage``.
|
||||
'''
|
||||
self.running = True
|
||||
while self.running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
self.running = False
|
||||
elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
|
||||
self.running = False
|
||||
elif event.type in self.tasks:
|
||||
self.run_task(event.type)
|
||||
else:
|
||||
self.display.dispatch_event(event)
|
||||
pygame.display.update()
|
||||
self.clock.tick(self.FRAME_RATE)
|
||||
self.display.broadcast(ShutdownMessage(self))
|
||||
When the loop is exited (by clicking the window close button or
|
||||
pressing the ``escape`` key) it broadcasts a ``ShutdownMessage``.
|
||||
'''
|
||||
self.running = True
|
||||
while self.running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
self.running = False
|
||||
elif event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:
|
||||
self.running = False
|
||||
elif event.type in self.tasks:
|
||||
self.run_task(event.type)
|
||||
else:
|
||||
self.display.dispatch_event(event)
|
||||
pygame.display.update()
|
||||
self.clock.tick(self.FRAME_RATE)
|
||||
self.display.broadcast(ShutdownMessage(self))
|
||||
|
||||
Reference in New Issue
Block a user