text: """Circuits using implementation of a Python module (plugin) manager for Naali.
  
  here is a Manager that the PythonScriptModule instanciates, 
  and which then loads the python modules that are to be autoloaded.
  This handles their event registrations, passing incoming events to them etc.
  """
  try:
      import rexviewer as r
  except ImportError: #not running under rex
      import mockviewer as r
  from circuits import handler, Event, Component, Manager, Debugger
  from core.logger import NaaliLogger
  #is not identical to the c++ side, where x and y have abs and rel
  #XXX consider making identical and possible wrapping of the c++ type
  #from collections import namedtuple
  #MouseInfo = namedtuple('MouseInfo', 'x y rel_x rel_y')
  from core.mouseinfo import MouseInfo
  
  #XXX a temporary fix 'cause circuits socket internals depend on a Started event now
  from circuits.core.events import Started
  
  class Key(Event): pass
  class Update(Event): pass     
  class Chat(Event): pass    
  class Input(Event): pass
  class MouseMove(Event): pass
  class MouseClick(Event): pass
  class SceneAdded(Event): pass
  class EntityUpdate(Event): pass
  class Exit(Event): pass
  class LoginInfo(Event): pass
  class InboundNetwork(Event): pass
  class GenericMessage(Event): pass
  class Logout(Event): pass
  class WorldStreamReady(Event): pass
      
  class ComponentRunner:
      instance = None
      
      def __init__(self):
          # instanciated from the c++ side, as modulemanager there
          #assert self.instance is None
          ComponentRunner.instance = self #is used as a singleton now. is this needed anywhere actually? XXX
          
          self.mouseinfo = MouseInfo(0,0,0,0)
          #m.start() #instead we tick() & flush() in update
          
          self.firstrun = True
          r.restart = False
          self.start()
          r.manager = self
  
      def start(self):
          # Create a new circuits Manager
          #ignevents = [Update, MouseMove]
          ignchannames = ['update', 'started', 'on_mousemove', 'on_mousedrag', 'on_keydown', 'on_input', 'on_mouseclick', 'on_entityupdated', 'on_exit', 'on_keyup', 'on_login', 'on_inboundnetwork', 'on_genericmessage', 'on_scene', 'on_entity_visuals_modified', 'on_logout', 'on_worldstreamready', 'on_sceneadded']
          ignchannels = [('*', n) for n in ignchannames]
          
          # Note: instantiating Manager with debugger causes severe lag when running as a true windowed app (no console), so instantiate without debugger
          # Fix attempt: give the circuits Debugger a logger which uses Naali logging system, instead of the default which writes to sys.stderr
          # Todo: if the default stdout is hidden, the py stdout should be changed
          # to something that shows e.g. in console, so prints from scripts show
          # (people commonly use those for debugging so they should show somewhere)
          d = Debugger(IgnoreChannels = ignchannels, logger=NaaliLogger()) #IgnoreEvents = ignored)
          self.m = Manager() + d
          #self.m = Manager()
  
          #or __all__ in pymodules __init__ ? (i.e. import pymodules would do that)
          if self.firstrun:
              import autoload
              self.firstrun = False
          else: #reload may cause something strange sometimes, so better not do it always in production use, is just a dev tool.
              #print "reloading autoload"
              import autoload
              autoload = reload(autoload)            
          #print "Autoload module:", autoload
          autoload.load(self.m)
  
          self.m.push(Started(self.m, None)) #webserver requires this now, temporarily XXX
                      
      def run(self, deltatime=0.1):
          #print "."
          self.send_event(Update(deltatime), "update") #so that all components are updated immediately once for this frame
          #XXX should this be using the __tick__ mechanism of circuits, and how?
          m = self.m
          m.tick()
  
      def send_event(self, event, channel):
          """simulate sync sending of events using the async lib.
          needed to be able to return the info of whether the event is to be
          send to more handlers on the c++ side in the Naali event system"""
          m = self.m
          ret = m.push(event, channel)
          while m: m.flush() #circuits components evaluate to false when have no pending events left
          if not ret.errors:
              #print "EVENT:", event, ret.value
              return True in ret #circuits return values implement __contains__ for this use case
          else:
              #did the debugger already show the traceback?
              return False
          
      def RexNetMsgChatFromSimulator(self, frm, message):
          self.send_event(Chat(frm, message), "on_chat")
          
      def INPUT_EVENT(self, evid):
          """Note: the PygameDriver for circuits has a different design:
          there the event data is Key, and the channel either "keydown" or "keyup",
          and mouse and clicks are different events and channels.
          Here we have no way to differentiate presses/releases,
          'cause the c++ internals don't do that apart from the constant name.
          """
          #print "circuits_manager ComponentRunner got input event:", evid       
          return self.send_event(Input(evid), "on_input")
          
      def KEY_INPUT_EVENT(self, evid, keycode, keymod):
          """Handles key inputs, creates a Circuits Key event with the data provided
          WIP, since on_keydown call doesn't work for now, resorted in using Input(keycode)
          instead, works similarly but still not the way it should
          """
          
          #print "CircuitManager received KEY_INPUT (event:", evid, "key:", keycode, "mods:", keymod, ")"
          #print r.KeyPressed, r.KeyReleased
          if evid == 39: #r.KeyPressed:
              return self.send_event(Key(keycode, keymod), "on_keydown")
          elif evid == 40: #r.KeyReleased:
              return self.send_event(Key(keycode, keymod), "on_keyup")
              
      def MOUSE_DRAG_INPUT_EVENT(self, event, x_abs, y_abs, x_rel, y_rel):
          self.mouseinfo.setInfo(x_abs, y_abs, x_rel, y_rel)
          #print "CircuitsManager got mouse movement", self.mouseinfo, self.mouseinfo.x, self.mouseinfo.y
          return self.send_event(MouseMove(event, self.mouseinfo), "on_mousedrag")
          
      def MOUSE_INPUT_EVENT(self, event, x_abs, y_abs, x_rel, y_rel):
          #print "CircuitsManager got a mouse click", mb_click, x_abs, y_abs, x_rel, y_rel
          #print "CircuitsManager", event
          self.mouseinfo.setInfo(x_abs, y_abs, x_rel, y_rel)
          if event == 60: #r.MouseMove:
              return self.send_event(MouseMove(event, self.mouseinfo), "on_mousemove")
              #return self.send_event(Mouse(event, self XXX
          else:
              return self.send_event(MouseClick(event, self.mouseinfo), "on_mouseclick")
  
  ##    def SCENE_EVENT(self, evid, entid):
  ##        return self.send_event(EntityUpdate(evid, entid), "on_scene")
  
      def SCENE_ADDED(self, name):
          return self.send_event(SceneAdded(name), "on_sceneadded")
          
      def ENTITY_UPDATED(self, entid):
          #print "Entity updated!", entid
          return self.send_event(EntityUpdate(entid), "on_entityupdated")
  
      def ENTITY_VISUALS_MODIFIED(self, entid):
          return self.send_event(EntityUpdate(entid), "on_entity_visuals_modified")
  
      def LOGIN_INFO(self, id): 
          #print "Login Info", id
          #return self.send_event(LoginInfo(id), "on_login") #XXX so wasn't needed or?
          return False
      
      def SERVER_DISCONNECTED(self, id):
          #print "Circuits got the server disconnection event."
          return self.send_event(Logout(id), "on_logout")
          
      def INBOUND_NETWORK(self, id, name):
          #print "Circuits got network_in event:", id, name
          return self.send_event(InboundNetwork(id, name), "on_inboundnetwork")
          ##r.randomTest(id) #for testing whether the id gotten is the same after a circulation on the python, note: worked
  
      def GENERIC_MESSAGE(self, typename, data):
          #print "Circuits got Generic Message event:", data
          return self.send_event(GenericMessage(typename, data), "on_genericmessage")
  
      def WORLD_STREAM_READY(self, event_id):
          return self.send_event(WorldStreamReady(event_id), "on_worldstreamready")
                 
      def exit(self):
          r.logInfo("Circuits manager stopping...")
          self.send_event(Exit(), "on_exit") #was originally not running the manager properly so the stop doesn't propagate to components. fix when switch to dev branch of circuits XXX
          self.m.stop() #was not going to components now so made the exit event above as a quick fix
          while self.m: self.m.flush()
          
      def restart(self):
          #r.restart = True
          r.logInfo("Restarting python module manager, reloading plugin codes")
          self.exit()
          self.start()
          r.logInfo("...done python restart.")
          #r.restart = False
                  
  #TestModule moved to own file (err, module)
  
  """
  why not allow plain functions as event handlers too,
  the python module of it, i.e. the file, can be considered as the module,
  so no classes are required.
  
  circuits has it so that you are supposed to make components.
  """
  
  #~ @e.communication.PRESENCE_STATUS_UPDATE
  #~ def sparkle_presence_updates():
      #~ """a custom visual thing: some local sparkles upon IM presence updates.
      #~ what data do we have in these events? the im participant id?
      #~ is that associated to an avatar anywhere? so could e.g. get the location..
      #~ """
      #~ create_sparkle((0,2, 0,2), 0.5) #in upper right corner, for half a sec
      
  if __name__ == '__main__':
      runner = ComponentRunner()
  
      import time
      while True:
          runner.run(0.1)
          #runner.RexNetMsgChatFromSimulator("main..", "hello")
          """
          rvalue = runner.KEY_INPUT_EVENT(3, 46, 0)
          if rvalue:
              print "returned true"
          else:
              print "returned false"
              
          """
          runner.MOUSE_INPUT(5, 6, 7, 8)
          time.sleep(0.01)
  
  
  