My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
CodeReloading  
Modified game or mudlib code is automatically put into play.
Phase-Implementation, Featured
Updated Dec 24, 2009 by richard.m.tew@gmail.com

Introduction

Code reloading stream-lines development. When code managed by the code reloading system is modified, the system detects the file changes and puts them in place. There is no need to restart the MUD in order to accomplish the same effect in a reliable way.

Details

The code reloading system is based around custom code loading, and placement of what that code defines into custom namespaces which you can then import it from. A game can specify any number of base namespaces, and for each, it needs to associate a given script directory where the code to be made available within that namespace is found. You can read more about these script directories on another page.

The external code reloading project can be referred to, if more insight than is provided here is desired.

Screencast

The following video illustrates a simple situation where the presence code reloading allows the developer to quickly make a desired change, and employ it in game. The scenario is that the output of the "commands" command displays an unsorted list, and the video covers the changing of this behaviour.

Unit Testing

Because scripts managed by the code reloading system cannot be executed outside of the system, the existing unit testing mechanism does not work. For the code to work, the game needs to be started up and running, and then it is in a place where it can be unit tested. The framework has extensive support for unit testing, including not automatically putting script changes in place if its unit tests fail. You can read more about this on the unit testing page.

Limitations

Normal Python Modules

This system overlays the standard Python module system. Modules in the standard library, or present in specified directories can still be imported in exactly the same way as before. But the code managed by the code reloading system is in this separate system.

Note: As code provided from standard modules is handled by a completely separate mechanism than the code reloading system, it does not get the code reloading behaviour. Either the framework needs to be restarted, or the standard Python reload function needs to be utilised. Of course it is worth keeping in mind that if this function was really that useful, this custom code reloading system would not be required.

Code Reloading Limitations

While the Python language allows a lot of dynamic behaviour, there are some things that cannot be modified or manipulated at runtime. Because of this, there are some cases in which changed code cannot be put into immediate effect.

Executing Code

You cannot change the code out from underneath an executing function. As long as the function call has not exited, it continues to use the code which was in place when it was first called. And given that this framework is based on Stackless Python and its microthreads, functions can execute for as long as the game runs.

The primary case to watch out for is infinite loops. A common pattern is to have an infinite loop that blocks waiting for some data, before processing that data and blocking waiting for more.

This following code shows a loop that is awakened when a connection is accepted, calling a secondary function to do the actual handling logic. This has already been structured to work around the described problem, but it still remains to a minimal degree.

    def AcceptTelnetConnections(self, listenSocket):
        acceptNonLocal = int(sorrows.data.config.net.acceptnonlocal)

        while self.IsRunning():
            currentSocket, clientAddress = listenSocket.accept()
            self.AcceptTelnetConnection(currentSocket, clientAddress, acceptNonLocal)

By calling AcceptTelnetConnection to handle a just accepted connection, the latest code for the handling logic will be employed. But the shown AcceptTelnetConnections code will always be the version used for the loop within it. Let's say that we decide that we no longer want to both passing in the acceptNonLocal argument to AcceptTelnetConnection, we can make this change, but there is no way to update this running function to use it.


Sign in to add a comment
Powered by Google Project Hosting