advanced.py :  » Development » Lyntin » lyntin-4.2 » lyntin » modules » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Lyntin 
Lyntin » lyntin 4.2 » lyntin » modules » advanced.py
#########################################################################
# This file is part of Lyntin.
#
# Lyntin is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Lyntin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# copyright (c) Free Software Foundation 2001-2007
#
# $Id: advanced.py,v 1.9 2007/09/30 02:02:50 willhelm Exp $
#########################################################################
"""
This module holds the magical python_cmd code.  It takes in code,
and attempts to execute it in the lyntinuser.py module.  If no such
module exists, it executes it in this module.

It also holds load_cmd which does a lot of other magic stuff.
"""
import sys
import StringIO
from code import compile_command
from lyntin import exported,config

usermodule = None
execdictglobals = None
execdictlocals = None

def _get_user_module():
  """
  Imports and returns the nicest user module it can find.  If we've
  already loaded a usermodule, then we use the cached one we
  loaded before so we're not doing this over and over again.

  @returns: the user module we just loaded or None
  @rtype: module
  """
  global usermodule
  if usermodule:
    return usermodule

  # this probably isn't exactly right since it'll look for the
  # first "lyntinuser" it finds and use that one.  i'm not sure how
  # we could implement a priority.
  for mem in sys.modules.keys():
    modname = "lyntinuser"
    if mem == modname or mem.endswith("." + modname):
      return sys.modules[mem]

  return None


def python_cmd(ses, words, input):
  """
  #@ allows you to execute arbitrary Python code inside of Lyntin.
  It will first look for a module named "lyntinuser" and execute
  the code inside that module's __dict__ environment.  If no
  such module exists, it will execute the code inside 
  modules.advanced .  At present it can only handle one-line
  Python statements.

  examples:
    #@ print "hello"
    #@ print "\\n".join(exported.get_commands())

  category: commands
  """
  global execdictglobals, execdictlocals

  # NOTE: if we ever get to handling multiple-lines, we'll need
  # to change this function completely.

  try:
    if execdictlocals == None:
      execdictlocals = {}
      
    execdictlocals["session"] = ses
    execdictlocals["exported"] = exported

    my_usermodule = _get_user_module() 
    if my_usermodule:
      dictglobals = my_usermodule.__dict__
    else:
      if execdictglobals == None:
        execdictglobals = {}
        exported.write_error("No lyntinuser module loaded--executing with no context.")
      dictglobals = execdictglobals

    source = input[1:].lstrip()
    compiled = compile_command(source)

    #
    # XXX for one-liners only:
    #
    if not compiled:
      compiled = compile_command(source+"\n")

    old_stdout = sys.stdout
    old_stderr = sys.stderr
    old_stdin = sys.stdin
    sys_stdout = StringIO.StringIO()
    sys_stderr = StringIO.StringIO()
    sys_stdin = StringIO.StringIO()
    try:
      sys.stdout = sys_stdout
      sys.stderr = sys_stderr
      sys.stdin = sys_stdin
      
      exec compiled in dictglobals, execdictlocals

    finally:
      sys.stdout = old_stdout
      sys.stderr = old_stderr
      sys.stdin = old_stdin
      
    error = sys_stderr.getvalue()
    if error:
      exported.write_error(error)

    text = sys_stdout.getvalue()
    if text.endswith("\n"):
      text = text[:-1]
    if text:  
      exported.write_message(text)  

  except (OverflowError, SyntaxError, ValueError, NameError):
    import traceback
    exported.write_error("".join(traceback.format_exception_only( *(sys.exc_info()[:2]) )))

  except:
    exported.write_traceback("@: error in raw python stuff.")
    exported.tally_error()


def load_cmd(ses, args, input):
  """
  Loads/reloads a module.

  When reloading, it looks for an "unload" function and executes 
  it prior to reloading the module.  After reloading/loading, it 
  looks for a "load" function and executes it.

  Lyntin modules located in the modules package are safe to reload 
  in-game.  Lyntin core modules (engine, helpmanager, event...) are
  NOT safe to import in-game.

  examples:
    #load modules.action
    #load exportuser

  #load will look for the module on the sys.path.  So if your module
  is not on the sys.path, you should first add the directory using #@:

    #@ import sys
    #@ sys.path.append("/directory/where/my/module/exists")

  Directories specified by the moduledir command-line argument are
  added to the sys.path upon Lyntin startup.

  category: commands
  """
  mod = args["modulename"]
  reload = args["reload"]

  # if this module has previously been loaded, we try to reload it.
  if sys.modules.has_key(mod):

    _module = sys.modules[mod]
    _oldmodule = _module
    try:
      if _module.__dict__.has_key("lyntin_import"):
        # if we're told not to reload it, we toss up a message and then
        # do nothing
        if not reload:
          exported.write_message("load: module %s has already been loaded." % mod)
          return

        # if we loaded it via a lyntin_import mechanism and it has an
        # unload method, then we try calling that
        if _module.__dict__.has_key("unload"):
          try:
            _module.unload()
          except:
            exported.write_traceback("load: module %s didn't unload properly." % mod)
      del sys.modules[mod]
      exported.write_message("load: reloading %s." % mod)

    except:
      exported.write_traceback("load: had problems unloading %s." % mod)
      return
  else:
    _oldmodule = None


  # here's where we import the module
  try:
    _module = __import__( mod )
    _module = sys.modules[mod]

    if (_oldmodule and _oldmodule.__dict__.has_key("reload")):
      try:
        _oldmodule.reload()
      except:
        exported.write_traceback("load: had problems calling reload on %s." % mod)
    
    if (_module.__dict__.has_key("load")):
      _module.load()

    _module.__dict__["lyntin_import"] = 1
    exported.write_message("load successful.")
    if mod not in config.lyntinmodules:
      config.lyntinmodules.append(mod)

  except:
    exported.write_traceback("load: had problems with %s." % mod)

def unload_cmd(ses, args, input):
  """
  Unloads a module from Lyntin by calling the module's "unload" function
  and then removing references to it in the Python environment.

  examples:
    #unload wbgscheduler
    #unload modules.alias

  category: commands
  """
  mod = args["modulename"]

  if sys.modules.has_key(mod):
    _module = sys.modules[mod]

    if _module.__dict__.has_key("lyntin_import"):
      if _module.__dict__.has_key("unload"):
        try:
          _module.unload()
        except:
          exported.write_traceback("unload: module %s didn't unload properly." % mod)
      else:
        exported.write_error("unload: module %s doesn't have an unload function." % mod)

      del sys.modules[mod]
      exported.write_message("unload: module %s unloaded." % mod)
      config.lyntinmodules.remove(mod)
      return
    else:
      exported.write_error("unload: module %s cannot be unloaded." % mod)
      return

  exported.write_error("unload: module %s is not loaded." % mod)


def load():
  exported.add_command("@", python_cmd)
  exported.add_command("^load", load_cmd, "modulename reload:boolean=true")
  exported.add_command("^unload", unload_cmd, "modulename")

def unload():
  exported.remove_command("@")
  exported.remove_command("^load")
  exported.remove_command("^unload")

# Local variables:
# mode:python
# py-indent-offset:2
# tab-width:2
# End:
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.