Limnoria/src/world.py

223 lines
8.6 KiB
Python

#!/usr/bin/env python
###
# Copyright (c) 2002, Jeremiah Fincher
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
Module for general worldly stuff, like global variables and whatnot.
"""
import fix
import gc
import os
import sre
import time
import types
import atexit
try:
import msvcrt
except ImportError:
pass
import conf
import debug
startedAt = 0.0
threadsSpawned = 0
commandsProcessed = 0
###
# End Global Values.
###
try:
ignore(ircs)
except NameError:
ircs = []
try:
ignore(flushers)
except NameError:
flushers = [] # A periodic function will flush all these.
def flush():
"""Flushes all the registered flushers."""
for f in flushers:
f()
try:
ignore(tempvars)
except NameError:
tempvars = {} # A storage place for temporary variables that need to be
# globally accessible.
def upkeep(): # Function to be run on occasion to do upkeep stuff.
"""Does upkeep (like flushing, garbage collection, etc.)"""
collected = gc.collect()
if os.name == 'nt':
try:
msvcrt.heapmin()
except IOError: # Win98 sux0rs!
pass
if gc.garbage:
debug.msg('Uncollectable garbage: %s' % gc.garbage, 'normal')
if 'noflush' not in tempvars:
flush()
debug.msg('Regexp cache size: %s' % len(sre._cache), 'verbose')
msg = '%s upkeep ran.' % time.strftime(conf.logTimestampFormat)
debug.msg(msg, 'verbose')
return collected
atexit.register(upkeep)
'''
def superReload(oldmodule):
###
# So here is how this baby works:
# Reload the module.
# Iterate through the old module, finding classes and functions that are
# also in the new module.
# Add an __getattribute__ or __getattr__ method to those classes that are
# present in the new module. This method will, when called, change
# the __class__ of the instance to point to the new class.
# Change the func_code, func_defaults, and func_doc of any functions or
# methods or generators we run across, just in case someone is holding
# a reference to them instead of calling them by name.
###
"""Reload a module and make objects auto-update."""
# reload(module) modifies module in-place, so we need a copy of its
# __dict__ to iterate through.
olddict = copy.copy(oldmodule.__dict__)
newmodule = reload(oldmodule)
newdict = newmodule.__dict__
for (name, oldvalue) in olddict.iteritems():
if name in newdict:
newvalue = newdict[name]
oldtype = type(oldvalue)
# We have to pass in newvalue because of Python scoping.
def updater(self, s, newvalue=newvalue):
# This function is to be an __getattr__ or __getattribute__.
try:
self.__class__ = newvalue
except:
debug.recoverableException()
try:
del self.__class__.__getattribute__
except AttributeError:
del self.__class__.__getattr__
return getattr(self, s)
if oldtype == types.TypeType and \
oldvalue.__module__ == newmodule.__name__:
# New-style classes support __getattribute__, which is
# called on *any* attribute access, so they get updated
# the first time they are used after a reload.
if not (issubclass(oldvalue, str) or \
issubclass(oldvalue, long) or \
issubclass(oldvalue, tuple)):
oldvalue.__getattribute__ = updater
elif oldtype == types.ClassType and\
oldvalue.__module__ == newmodule.__name__:
# Old-style classes can only use getattr, so they might not
# update right away. Hopefully they will, but to solve
# this problem I just use new-style classes.
oldvalue.__getattr__ = updater
elif oldtype == type(newvalue):
if oldtype == types.FunctionType or\
oldtype == types.GeneratorType:
oldvalue.func_code = newvalue.func_code
oldvalue.func_defaults = newvalue.func_defaults
oldvalue.func_doc = newvalue.func_doc
elif oldtype == types.MethodType:
oldfunc = oldvalue.im_func
newfunc = newvalue.im_func
oldfunc.func_code = newfunc.func_code
oldfunc.func_defaults = newfunc.func_defaults
oldfunc.func_doc = newfunc.func_doc
# Update the linecache, so tracebacks show the proper lines.
linecache.checkcache()
return newmodule
'''
try:
# This makes the module reload properly; we don't want to lose oldobjects
# on reload.
oldobjects
except NameError:
oldobjects = {}
def superReload(module):
"""Reloads a module hardcore. But kinda broken -- don't use it."""
def updateFunction(old, new, attrs):
"""Update all attrs in old to the same attrs in new."""
for name in attrs:
setattr(old, name, getattr(new, name))
for (name, object) in module.__dict__.iteritems():
# For every attribute of the old module, keep the object.
key = (module.__name__, name)
oldobjects.setdefault(key, []).append(object)
module = reload(module)
for name, newobj in module.__dict__.iteritems():
# For every attribute in the new module...
key = (module.__name__, name)
if key in oldobjects: # If the same attribute was in the old module...
for oldobj in oldobjects[key]:
# Give it the new attributes :)
if type(newobj) == types.ClassType:
toRemove = []
for k in oldobj.__dict__:
if k not in newobj.__dict__:
toRemove.append(k)
for k in toRemove:
del oldobj.__dict__[k]
oldobj.__dict__.update(newobj.__dict__)
# elif type(newobj) == types.TypeType:
# if hasattr(oldobj, '__dict__'):
# oldobj.__dict__.update(newobj.__dict__)
elif type(newobj) == types.FunctionType:
updateFunction(oldobj, newobj, ('func_code',
'func_defaults',
'func_doc'))
elif type(newobj) == types.MethodType:
updateFunction(oldobj.im_func, newobj.im_func,
('func_code', 'func_defaults', 'func_doc'))
return module
#################################################
#################################################
#################################################
## Don't even *think* about messing with this. ##
#################################################
#################################################
#################################################
startup = False
testing = False
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: