Showing posts with label code reloading. Show all posts
Showing posts with label code reloading. Show all posts

Tuesday, 7 September 2010

Roguelike MUD progress #4

Previous post: Roguelike MUD progress #3

Almost no progress on the game today. Instead, I was distracted by two different problems with my code reloading framework. Link to SVN revision.

  1. Use of slots:
    class Tile(object):
    __slots__ = [ "character", "fgColour", "bgColour", "flags" ]
    This also seems to be an unsolved problem in the xreload module, which was written for normal Python namespaces.

    TypeError: descriptor 'flags' for 'Tile' objects doesn't apply to 'Tile' object

    I've not got any better ideas, and I am only using __slots__ for the sake of it. So the solution is to stop using them.

  2. File-local instances of the classes it defines:
    START_TILE = Tile("x", isMarker=True)
    SPAWN_TILE = Tile("s", isMarker=True)
    WALL_TILE = Tile("X", isPassable=False, isOpaque=True)
    WALL1_TILE = Tile("1", isPassable=False, isOpaque=True)
    WALL2_TILE = Tile("2", isPassable=False, isOpaque=True)
    DOOR_TILE = Tile("D")
    FLOOR_TILE = Tile(" ")

    mapTilesByCharacter = {}
    def IndexTiles():
    for k, v in globals().iteritems():
    if k.endswith("_TILE"):
    mapTilesByCharacter[v.character] = v
    IndexTiles()

    CHAR_TILE_TEMPLATE = Tile("@", isPassable=False)
    DRAGON_TILE = Tile("&", isPassable=False)
    I've had to use a custom framework that has xreload-based code reloading, and encountered this same scenario there. In that case, it was because the class was registered with a external factory and subsequently used to churn out bad instances. These then hit the following error.

    unbound method BLAH must be called with BLAH instance as first argument (got BLAH instead)

    Solving that leaked class problem was simple, through locating the references to the throwaway new class, and substituting the old reference for them. Replacing instances though, is a little more complicated.

    This error has gone away in 3.x I am told, which is a pity. As it serves as a good indication that there instances or class references have leaked outside of the code reloading system.
Chances are that I am going to have to try and solve these cases for xreload, as well as in my custom framework.

Next post: Roguelike MUD progress #5

Monday, 1 February 2010

Patching through code modification

Previous post: Tracking class instantiations

As I have been exploring patching __init__ of classes loaded by my code reloading framework so that I can track creation of instances, I've been considering other approaches.

In the previous post, where there was an existing __init__ method, I renamed it and had my replacement __init__ call it before it registered the freshly created instance. But I can do better, if I modified the bytecode of the existing method, I could inject my registration call directly into it. As an optimisation, in this case it does not add much. But it is interesting to look into, and there is the possibility that this sort of functionality can be added in a more general way within the code reloading framework.

I found three commonly mentioned bytecode manipulating frameworks:

  • bytecodehacks: No longer maintained and out of date for 2.6.
  • BytecodeAssembler: Lots of dependencies and it only allows creation of bytecode, not modification of existing bytecode.
  • byteplay: One file, allows modification of existing code, works out of the box.
byteplay looks like the only suitable candidate that I can just pick up and use.

Code to be modified:
>>> class Test:
... def __init__(self):
... if f():
... print 1
... return
... if g():
... print 2
... return
... print 3
...
I want to make my injected call after the logic in the function has been executed, but before it returns. In this function, there are multiple return points.

Passing the code into byteplay:
>>> import byteplay
>>> c = byteplay.Code.from_code(Test.__init__.func_code)
>>> print c.code

3 1 LOAD_GLOBAL f
2 CALL_FUNCTION 0
3 JUMP_IF_FALSE to 13
4 POP_TOP

4 6 LOAD_CONST 1
7 PRINT_ITEM
8 PRINT_NEWLINE

5 10 LOAD_CONST None
11 RETURN_VALUE
>> 13 POP_TOP

6 15 LOAD_GLOBAL g
16 CALL_FUNCTION 0
17 JUMP_IF_FALSE to 27
18 POP_TOP

7 20 LOAD_CONST 2
21 PRINT_ITEM
22 PRINT_NEWLINE

8 24 LOAD_CONST None
25 RETURN_VALUE
>> 27 POP_TOP

9 29 LOAD_CONST 3
30 PRINT_ITEM
31 PRINT_NEWLINE
32 LOAD_CONST None
33 RETURN_VALUE
Basically I want to inject my call before each LOAD_CONST None/RETURN_VALUE pair.

Code to inject:
>>> def f(self):
... events.Register(self)
Passing the code into byteplay:
>>> c2 = byteplay.Code.from_code(f.func_code)
>>> print c2.code

2 1 LOAD_GLOBAL events
2 LOAD_ATTR Register
3 LOAD_FAST self
4 CALL_FUNCTION 1
5 POP_TOP

6 LOAD_CONST None
7 RETURN_VALUE
Basically I want to select the bytecode entries matching displayed lines 1 through 7 and insert them in place of any existing pairs as described above. But something these bytecode listings do not show, is that line numbers are also marked up with bytecode entries. So I need to make sure I do not obliterate existing line numbers in the code I am modifying, or copy over line numbers in the code I am injecting.

Injecting the call before the returns:
offset = len(c.code) - 1
lastInstruction = None
while offset >= 0:
instruction, value = c.code[offset]
if lastInstruction == byteplay.RETURN_VALUE and \
instruction == byteplay.LOAD_CONST:
c.code[offset:offset+2] = c2.code[1:]
lastInstruction = instruction
offset -= 1
The resulting bytecode:
>>> print c.code

3 1 LOAD_GLOBAL f
2 CALL_FUNCTION 0
3 JUMP_IF_FALSE to 18
4 POP_TOP

4 6 LOAD_CONST 1
7 PRINT_ITEM
8 PRINT_NEWLINE

5 10 LOAD_GLOBAL events
11 LOAD_ATTR Register
12 LOAD_FAST self
13 CALL_FUNCTION 1
14 POP_TOP
15 LOAD_CONST None
16 RETURN_VALUE
>> 18 POP_TOP

6 20 LOAD_GLOBAL g
21 CALL_FUNCTION 0
22 JUMP_IF_FALSE to 37
23 POP_TOP

7 25 LOAD_CONST 2
26 PRINT_ITEM
27 PRINT_NEWLINE

8 29 LOAD_GLOBAL events
30 LOAD_ATTR Register
31 LOAD_FAST self
32 CALL_FUNCTION 1
33 POP_TOP
34 LOAD_CONST None
35 RETURN_VALUE
>> 37 POP_TOP

9 39 LOAD_CONST 3
40 PRINT_ITEM
41 PRINT_NEWLINE
42 LOAD_GLOBAL events
43 LOAD_ATTR Register
44 LOAD_FAST self
45 CALL_FUNCTION 1
46 POP_TOP
47 LOAD_CONST None
The next step is to make f, g and events, and to execute the modified bytecode.

Testing the bytecode:
>>> def f(): return False
...
>>> def g(): return False
...
>>> Test.__init__.im_func.func_code = c.to_code()
>>> class Events:
... def Register(self, instance):
... print "REGISTERED", instance
...
>>> events = Events()
>>> t = Test()
3
REGISTERED <__main__.Test instance at 0x01D2DAD0>
Excellent. I'll have to think about the possibilities for this. It has potential to allow the creation of all sorts of interesting features in a code reloading framework.

Saturday, 30 January 2010

Tracking class instantiations

One of the experiments I have been doing based on code reloading, is to among other things, add the ability to react to instantiations of arbitrary classes. The way I go about doing this is to react to the definition of a class by giving it a new __init__ method.

If the class came with a custom __init__ method, then this is the easiest case to handle. When my replacement method is called, I can just call the original custom method before I notify whatever is interested.

    def init_wrapper(self, *args, **kwargs):
class_.__real_init__(self, *args, **kwargs)
events.Register(self)
What gets a little more complex, is the case when the class does not have a custom __init__ method defined. In this situation, I still need to notify whatever is interested, but in order to preserve existing behaviour I need to pass the call down to the base classes.
    def init_standin(self, *args, **kwargs):
if type(self) is types.InstanceType:
# Old-style..
for baseClass in class_.__bases__:
if hasattr(baseClass, "__init__"):
baseClass.__init__(self, *args, **kwargs)
else:
# New-style..
super(class_, self).__init__(*args, **kwargs)
events.Register(self)
The thing that really complicates this, is the class_ variable used in the both snippets included above. This needs to refer to the class that the given method being executed is defined on. I cannot infer the class from any of the existing variables, so it needs to be provided in some other way. Because I know it when I install the __init__ method, I define these functions inline so their use of it includes it in their closures.
    def MonitorClassInstantiation(self, class_):
def init_wrapper(self, *args, **kwargs):
class_.__real_init__(self, *args, **kwargs)
events.Register(self)

def init_standin(self, *args, **kwargs):
if type(self) is types.InstanceType:
for baseClass in class_.__bases__:
if hasattr(baseClass, "__init__"):
baseClass.__init__(self, *args, **kwargs)
else:
super(class_, self).__init__(*args, **kwargs)
events.Register(self)

init_real = class_.__dict__.get("__init__", None)
if init_real is None:
class_.__init__ = init_standin
else:
class_.__init__ = init_wrapper
class_.__real_init__ = init_real
With this working, the remaining concern is the effect of a hierarchy of classes modified in this way. Each has one of these two new __init__ methods, and the subclasses call down through them to the base classes. For now, I have a WeakKeyDictionary of instances in the events handler that ignores calls from instances that have already called.

Source code: events.py

Tuesday, 26 January 2010

Code reloading and event notifications

A problem with the use of code reloading is reconciling the changes made to code with how existing and new uses of that code are affected. I've been experimenting with removing this problem for users of my code reloading framework, in this case in the implementation of an event subscription and notification system for my MUD framework.

Without code reloading

The use case is notifying instances of a class when an event they are interested in occurs. If code reloading is not in use, the following code might be one way for a user to indicate interest in, and to receive events.

Manual event registration:

class Object(BaseObject):
__events__ = BaseObject.__events__ + [ "OnSomethingHappened" ]

def __init__(self):
BaseObject.__init__(self)
events.Register(self)

def OnSomethingHappened(self):
pass
But in taking this approach, the user needs to keep several things in mind. That they do not clobber the events the base class may register for. That they list the function names of new events in the __events__ list on the class. That the base class may do the registration as well, so either they need to check and only register locally, or just register a second time if they cannot be bothered with it.

With code reloading

If code reloading is used, then the manual registration becomes a potential problem. Should an event registration call get added to the class sometime during the development process, existing instances will not receive the new events. And as changes are made over time and further events are added, which instances receive them will depend on whether they were created after the appropriate change. This is bad because it complicates the model of possible behaviours and problems that the user has to keep in their head. The way it should work, is such that any changes made to code are automatically applied to existing uses of that code, where it is reasonable to do so.

By having the framework react to the live addition of a class in a namespace, further live updates to that class and subsequent instantiations of it, it should be possible to build on these things to make event subscription a lot simpler for the user.

Automatic event registration:
class Object(BaseObject):
def event_SomethingHappened(self):
pass
Here the user simply needs to know that if they prefix a function name on their class with event_, any instances whether already existing or yet to be created, will be guaranteed to receive it.

Implementation

The main goal is that event delivery should be direct and not require any additional work to identify valid subscribers. All the work would instead be done when code reloading takes place. This would be achieved by processing classes that are created or updated and determining what events they implicitly require notification of.

Code reloading event registration:
    def OnClassCreation(namespace, className, class_):
pass

def OnClassUpdate(class_):
pass

cr = reloader.CodeReloader()
cr.SetClassCreationCallback(OnClassCreation)
cr.SetClassUpdateCallback(OnClassUpdate)
Existing instances would be unsubscribed from events where methods are removed, and subscribed to events where methods are added. This is a little complicated. It should be a lot easier to react to creation of new instances. But getting notified about the creation of new instances without requiring boilerplate on the part of the user is not straightforward.

One way would be to replace a method involved in the instantiation of instances of the class, like __new__ or __init__. __new__ can be ruled out, as it only works for new-style classes. __init__ seems to be the likeliest choice. With the events notifying of class creation and updates, injecting a method into a given class is a straightforward extension.

Monkey-patched __init__ method:
    def __init__(self, *args, **kwargs):
self.__real_init__(self, *args, **kwargs)
events.TrackAndRegisterInstance(self)
But maybe there is an easier way to hook into instance creation that I am not aware of.

Conclusion

It is very possible for the user to change code in a way that is incompatible with existing use of that code. But I think that it is a valuable goal not to try and increase the number of ways that this might happen.

Some of the problems are caused by the way Python is implemented, like where functions in mid-execution (particularly when using Stackless) use the code that was in place when they started executing, and continue using it until they exit. In this case a user needs to add boilerplate to ensure that changed code is adopted.

Loop boilerplate:
    def Loop(self):
while self.running:
self._Loop()
Sleep(1.0)

def _Loop(self):
pass # Actual loop logic
Other problems are caused by the user making changes that are incompatible with existing use, like modifying functions on a class to use a new variable that only gets initialised for new instances in the accompanying new version of __init__. To illustrate this, if the counter variable is added to __init__ and _Loop, then existing instances will cause an AttributeError on their next call to _Loop.

Problem case:
class SomeObject(BaseObject):
def __init__(self):
self.counter = 1
...

...

def _Loop(self):
self.counter += 1
...
I don't have a good solution for this. It is one of those things the user just has to remain aware of. And in around eight years of using another code reloading solution, I cannot say that I really recall making this mistake myself. The only way I can conceive of dealing with it, is by analysing code changes using the AST or some other method of introspection.

In fact, given the direction I am heading, this might be worth exploring. If it can be done in a way where it does not become a further burden on the user, then definitely so.

Thursday, 21 January 2010

Strange class leakage

One of the ways in which code reloading can be implemented in Python, with respect to classes defined within managed scripts, is by updating the existing class in place.

The process resembles the following..

  1. The code reloading framework is started up, loading a main copy of every script file registered with it.
  2. The user modifies a script file.
  3. The code reloading framework detects and reacts to the file modification.
  4. The new version of the script file is executed into a dictionary.
  5. For every class in the dictionary that already existed..
    1. The original version of the class is retrieved from the main copy.
    2. Each valid dictionary entry in the new class is moved into the original class, overwriting whatever it had. If the entry is a function, it is rebuilt so that its internal func_globals dictionary points to that of the main copy, rather than the new copy.
  6. The new version of the script file is discarded and garbage collected, now that the main version has been updated to resemble it.
It is a lot less legwork than the alternate approach, which is wandering around the references in the garbage collector and replacing references to the original class.

Leakage

I use the code reloading framework in a MUD framework. One of the project's tasks that I am working on at the moment, is locating the commands which a logged in player can execute.

The original approach was to simply iterate over a given namespace and check if one of the contents was an instance of the Command class. However, as there are now multiple namespace locations where commands may be located, I decided to try an alternate approach. Instead I would find use the garbage collector to find all the subclasses of the Command class, and obtain the commands that way.
for class_ in pysupport.FindSubclasses(Command, inclusive=True):
for verb in class_.__verbs__:
if verb in self.verbs:
logger.warning("Duplicate '%s': %s", verb, class_)
continue
Each time I modified the rehash command, I started to see a ghost class appearing in the output of this logging action. So for the umpteenth time, I wrote some code to dig through the referrers in the garbage collector, in order to work out what was holding the references.

Tracking references

By passing the ghost classes to PrintReferrers, I see the following..
5 REFERRERS FOR <type 'classobj'> __builtin__.Rehash 0x20a84b0
SKIPPED/is-local-frame 0x20ebec8 <frame object at 0x020EBEC8>
SKIPPED/is-seen-list 0x20a9e90 <type 'list'>
SKIPPED/is-local-frame 0x20f7ae0 <frame object at 0x020F7AE0>
6 REFERRERS FOR <type 'list'> [ ... ] 0x20ae1e8
5 REFERRERS FOR <type 'listiterator'> 0x1c33110
SKIPPED/is-seen-list 0x20a9e90 <type 'list'>
SKIPPED/is-local-frame 0x1b1fc88 <frame object at 0x01B1FC88>
SKIPPED/is-referrer-list 0x20a9c10 <type 'list'>
SKIPPED/is-local-frame 0x1b1fe30 <frame object at 0x01B1FE30>
SKIPPED/is-local-frame 0x20f7ae0 <frame object at 0x020F7AE0>
SKIPPED/is-local-frame 0x20ebec8 <frame object at 0x020EBEC8>
SKIPPED/is-seen-list 0x20a9e90 <type 'list'>
SKIPPED/is-referrer-list 0x20a96c0 <type 'list'>
SKIPPED/is-local-frame 0x1b1fc88 <frame object at 0x01B1FC88>
SKIPPED/is-local-frame 0x20f7ae0 <frame object at 0x020F7AE0>
5 REFERRERS FOR <type 'dict'> { ... } 0x20aba50
SKIPPED/is-local-frame 0x20ebec8 <frame object at 0x020EBEC8>
SKIPPED/is-seen-list 0x20a9e90 <type 'list'>
SKIPPED/is-referrer-list 0x20a96c0 <type 'list'>
SKIPPED/is-local-frame 0x20cc188 <frame object at 0x020CC188>
5 REFERRERS FOR <type 'function'> 0x20a5eb0
SKIPPED/is-seen-list 0x20a9e90 <type 'list'>
SKIPPED/is-local-frame 0x20cc188 <frame object at 0x020CC188>
SKIPPED/is-referrer-list 0x20a9490 <type 'list'>
SKIPPED/is-local-frame 0x20cc330 <frame object at 0x020CC330>
5 REFERRERS FOR <type 'dict'> { ... } 0x20ab9c0
SKIPPED/is-seen-list 0x20a9e90 <type 'list'>
SKIPPED/is-local-frame 0x20cc330 <frame object at 0x020CC330>
SKIPPED/is-referrer-list 0x20a9ad0 <type 'list'>
SKIPPED/is-local-frame 0x20cf078 <frame object at 0x020CF078>
SKIPPED/seen 0x20a84b0 __builtin__.Rehash
I've trimmed some redundant information out by hand. But what it shows, is that the class has a function that has a dictionary, that has a reference to the class. Seeing what the contents of the trimmed containers were, it indicates that the normal func_globals reference is creating a circular reference and keeping the class alive.

All classes leak?

The first thing I did was rule out that this was simply the way that Python worked.

I created a script containing..
class AClass:
def AFunction(self):
pass
And then repeatedly reloaded the class in the interpreter..
>>> d = {}
>>> execfile("test.py", d, d)
>>> d = {}
>>> execfile("test.py", d, d)
>>> d = {}
>>> execfile("test.py", d, d)
>>> d = {}
>>> execfile("test.py", d, d)
>>> import gc, types
>>> for v in gc.get_objects():
... if type(v) is types.ClassType and v.__name__ == "AClass":
... print v
...
__builtin__.AClass
__builtin__.AClass
__builtin__.AClass
__builtin__.AClass
>>> gc.collect()
12
>>> for v in gc.get_objects():
... if type(v) is types.ClassType and v.__name__ == "AClass":
... print v
...
__builtin__.AClass
So outside of my framework Python does the correct thing.

Conclusion

Some possible reasons for what is going on:
  • My reference printing function is skipping something it shouldn't (not seeing it).
  • How I am calling execfile is creating this circular reference in a way that is somehow different (not seeing it).
For now, I will enter a defect and have the new script file clear its dictionary when it is garbage collected, which fixes the problem.

Writing this reference tracking code for the umpteenth time makes me wonder if something similar, but both tested and proven, is out there.

Wednesday, 13 January 2010

Sorrows mudlib: An event notification/subscription model, part 3

Previous post: Sorrows mudlib: An event notification/subscription model, part 2

I've settled on three methods of registering for events using my module. My events module will only directly support the first two, and while the third is my preferred approach, it requires the legwork to be done externally.

  1. Manual registration of object instances.
  2. Manual registration of direct callbacks.
  3. Automatic registration of object instances.
All of the following examples, assume the presence of a pre-existing instance of EventHandler, named events. Remember that what events an instance is registered for, is intended to be determined by the name of functions within the class of the instance. Specifically, functions named with the prefix of event_.

Manual registration of object instances

The most likely use of this approach, is an instance registering itself by a call within its __init__ function.
class SomeObject:
def __init__(self):
events.Register(self)
This approach is problematic however if you are using a code reloading system, like I am. Adding a call to Register within __init__ in a change to a relevant class, will leave existing instances unregistered for any events you have added. Removing a call to Register within __init__ in a change to a relevant class, will leave existing instances registered for any events they were previously registered for.

Manual registration of direct callbacks

Often there is a need to dynamically register a callback for events, which is what this approach allows.
class SomeObject:
def Callback(self):
pass

instance = SomeObject()
events.SomeEvent.Register(instance.Callback)
It also suffers from the same problems related to code reloading systems, as the previous approach.

Automatic registration of object instances

As mentioned at the top of this post, this approach has to be driven by external legwork. In my case, this will be my code reloading system. All a developer will have to do, is name a function intended to be notified of an event within a class, with the event_ prefix.
class SomeObject:
def event_SomeEvent(self):
pass
The external legwork would look something like the following.
def OnClassChanged(class_, instances):
oldEvents = getattr(class_, "__EVENTS__", set())

matches = eh.ProcessClass(class_)
if len(matches):
## Handle instances yet to be created.
old_init = class_.__init__
def new_init(self, *args, **kwargs):
eh.Register(self)
old_init(*args, **kwargs)
class_.__init__ = new_init

## Handle existing instances.
newEvents = set([ t[0] for t in matches ])

# Remove existing registrations.
removedEvents = oldEvents - newEvents
addedEvents = newEvents - oldEvents
matchesLookup = dict(matches)
for instance in instances:
for eventName in removedEvents:
eh._Unregister(eventName, instance)
functionName = matchesLookup[eventName]
for eventName in addedEvents:
eh._Register(eventName, instance, functionName)

class_.__EVENTS__ = newEvents
The code reloading system would be required to provide a callback notifying that a class had been changed, and also a list of the instances of the class that are in existence. This is information that the code reloading system would most likely have.

Conclusion

The event model is now ready for use in my MUD framework. I still need to decide how to make it available for use, whether through a built-in EventHandler instance or otherwise. And I still need to link it up to the code reloading system.

Source code: events.py

Monday, 11 January 2010

Sorrows mudlib: An event notification/subscription model, part 2

Previous post: Sorrows mudlib: An event notification/subscription model, part 1

At this time, my preferred approach is to identify event subscriptions by how functions are named within a given object.

    def event_OnServicesStarted(self):
However, when I think about functions simply receiving an event when it happens, using a simple decorator has some appeal.
    @event
def OnServicesStarted(self):
But I am not sure how extensive my event model is going to get. Do I want to allow a subscription to specify when it gets received, or how it gets received?

When events might get received

For some events, it is useful to know that you are receiving a notification before an event has had side-effects through its subscribers, when it is appropriate to act on it and cause side-effects or when all direct side-effects have happened.

A simple way to structure this is to allow subscription for one of three different partial broadcasts. The first, a pre-broadcast. The second, the actual broadcast. And the third, a post-broadcast.

Using the decorator syntax, subscription might happen in the following way.
    @event.pre
def OnServicesStarted(self): pass

@event
def OnServicesStarted(self): pass

@event.post
def OnServicesStarted(self): pass
Each decorated function will have the same name, and will overwrite any previous attribute on the class, specifically the event function before it. This means that this specific approach using decorators will not allow an object to register for more only one stage in the broadcast of a given event.

Using the name-based syntax, subscription might happen in the following way.
    def event_OnServicesStarted_pre(self): pass

def event_OnServicesStarted(self): pass

def event_OnServicesStarted_post(self): pass
This is a little more versatile than the decorator approach, as it allows an object to register for every stage in the broadcast of an event. Of course, to address this the function naming could be brought partially into the decorator approach, where the use of the _pre or _post suffix would have the same effect.

How events might get received

Using Stackless Python, my MUD framework cooperatively schedules the microthreads it is built upon. Cooperative scheduling is a lot simpler to program than preemptive scheduling, because you know where your code is going to block. You do not always want your code to block when you want to send an event, although at other times it might be acceptable.

So the broadcaster needs to be in control of how events get sent. They need to be able specify that a broadcast can block or not.

It might be done through a global function.
    event("OnServicesStarted")
Or avoiding the clunky string used for an event name.
    event.OnServicesStarted()
It is reasonable to assume this is how blocking event broadcasts are made, given that the natural expectation for a function call is for it to do processing and return. So, that leaves the question of how to do non-blocking event broadcasts.

One possibility, is a special attribute that injects differing behaviour.
    event.noblock.OnServicesStarted()
Here, the noblock attribute would simply return a secondary event object that starts event broadcasts in a new microthread.

Does this effect subscribers? Not unless a subscriber has the ability to interfere or interrupt a broadcast, which is not a desired part of this model. Event subscription does not need to know about, or cater for this. It is a broadcast related detail.

To decorate, or not

Not. There is no compelling reason, beyond appreciation of how it looks, to choose to use decorators. The function naming approach is fine for now, and does not cost an extra line of source code.

When are objects registered

It is all very well for objects to specify functions named in such a way that it is recognised they should be called when events happen. However, the object still needs to be registered for those events. What is the best way to go about this? How is the use of code reloading affected by this?

It is possible within the code reloading system, to set things up in such a way that when an object is instantiated, it automatically gets registered for events. The way this would work, is that when a class is first loaded, or subsequently reloaded, it would have event related post-processing applied. The code reloading system does not currently support this, but it is an easy feature to add to it.

A simpler approach, is to have any object which defines events, make an explicit call to the event system to register it for any events that it may handle. This would have to happen within the constructor for that object, the __init__ method. The problem is that this method is called when the object is instantiated, and if the registration call is added within a subsequent code change, existing instances of the object will never get registered. It complicates the model a programmer has to hold in their head about how effective code reloading is.

Taking care of registration with the aid of the code reloading system looks like the way to go.

Conclusion

I am pretty sure I have gone over what I need out of an event system. I have a preferred approach to how event subscriptions are declared. I have a preferred approach to how event broadcasts are made. At this point, implementation looks like the next step.

Next post: Sorrows mudlib: An event notification/subscription model, part 3
Source code: events.py

Saturday, 9 January 2010

Sorrows mudlib: An event notification/subscription model, part 1

One of the most important design decisions for my MUD codebase, is to be as decoupled as possible. The codebase is reasonably clean as a result of this, but there are many systems that need to be revisited. Some are a legacy of earlier versions of the codebase, and others have not had a real use made of them that would drive the evolution of their design.

One of these systems, the one I will examine in this blog post, is a generic system to both subscribe to events, and to broadcast events to existing subscribers. As I am currently at the stage where I am ready to build other systems that make use of this lower-level one, I need to reexamine how it currently works and consider whether it does what is needed, or if I can do better.

The current implementation

Currently, an object that wants to listen to the OnServicesStarted event needs to define specific elements on its class.

class Object:
__listenevents__ = [ "OnServicesStarted" ]

def OnServicesStarted(self):
pass
That is, for each event it wishes to receive, the name has to be present within a magic attribute. And of course, a handler function needs to be defined on the class with the same name as the matching event. Defining these elements does not provide automatic subscription however, the object still has to subscribe for the events it wishes to listen to.
class Object:
def __init__(self):
sorrows.services.AddEventListener(self)
The main downside of this approach is the boilerplate involved, where the name of the event needs to be declared and then a function of the same name defined. A lesser downside is that the services service does not seem like the most relevant place to go to for event registration.

This will be referred to as the magic attribute and handler method pattern.

Idea: An event service

Moving this functionality to a custom service seems a little cleaner. Objects would then call in the following way to subscribe:
    sorrows.events.AddListener(self)
But having this functionality in a custom service, means that any other service that wants to use it might need to declare the custom service as a dependency.
class GameLogicService(Service):
__dependencies__ = [ "events" ]
This adds boilerplate and complication where it can otherwise be avoided. Chances are that most services would end up with a dependency on the events service. One advantage of having this system within the services service, was that it was guaranteed to be available for all services regardless of whether they had started fully yet or not.

This is a dead end.

Idea: An event handler

A way to avoid the dependency problem, is to move this functionality outside of the service infrastructure, perhaps as an independent singleton object. The following code pretty much wrote itself, following the conception of this idea.
class Event:
registry = weakref.WeakValueDictionary()

def __init__(self, eventName):
self.name = eventName

def Wait(self):
c = self.registry.get(self.name, None)
if c is None:
c = self.registry[self.name] = stackless.channel()
return c.receive()
This is a break from the magic attribute and handler method pattern. How it would be used highlights this.
class SomeObject:
def __init__(self):
# .. do some setup first
stackless.tasklet(self.HandlePlayerLoginEvent)()

def HandlePlayerLoginEvent(self):
while True:
user = Event("PlayerLogin").Wait()
# .. do what we wanted to do to them
One of the advantages mooted about Stackless, or coroutines in general, is the ability to lessen boilerplate and to be able to write more readable code. This solution illustrates that advantage, although an obvious next step would be encapsulating the Event class instantiation and Wait method call into a simple function. It might be called WaitForEvent, taking the event name as an argument and blocking until it occurs, returning the relevant parameters.
def WaitForEvent(eventName):
return Event(eventName).Wait()
At this stage, I am distracting myself with details. The goal is a cleaner event system, rather than the lesser details of how that system would be used. But before I move on and forget, one last thought.. a thought occurs that passing the event name as a string is clunky, and that it might be cleaner to be able to do eventHandler.eventName and have that implicitly do the blocking the Wait method from above does. But these things can be explored when I have decided on the best system to make use of them with.

The current idea is quite appealing, especially because as described above, it moves towards the ideal of more readable code rather than disjoint callback-based boilerplate. But after sleeping on it, I remembered the advantage of having events declared as data, rather than within code. Or what the last idea had over this one. My mudlib uses a code reloading framework, and if things like events are declared within code, the code reloading support cannot be extended to automatically correct things like putting in place new event subscriptions. What if SomeObject was extended to handle a second event?
class SomeObject:
def __init__(self):
# .. do some setup first
stackless.tasklet(self.HandlePlayerLoginEvent)()
stackless.tasklet(self.HandlePlayerLogoffEvent)()
When the script defining this code is modified, and reloaded, instances of this class may already be out there in use. Their __init__ method will have already run as its old version, and it is unreasonable to expect the code reloading system to compare the two and reconcile the differences. They will inherit the new HandlePlayerLogoffEvent (not shown above of course), but will not be registered for the event.

With the magic attribute and handler method pattern, it is trivial to subscribe and unsubscribe objects for events as entries in the magic method come and go. Maybe it is time to take a step back..

Design requirements

So having examined two approaches, I have two highlighted design requirements. They are listed in order of priority.
  1. Integrated with code reloading support.
  2. Avoid boilerplate and allow use of synchronous syntax.
Idea: Inline event declaration

The synchronous approach as shown above is very appealing, but it is unreasonable to infer event registrations from within code. The events that need to be subscribed to, or unsubscribed from, have to be declared. If we were to go with the synchronous approach, we need to adapt it in some way to do this.

One solution is wrapping event handlers with a decorator that declares what event it handles.
    @event("PlayerLogin")
def HandlePlayerLogins(self):
user = WaitForEvent()
In my experience with other people making use of decorators, they tend to be more of a pollution than a benefit. Of course, with restraint, they are fine used only where really suitable and actually needed.

Considering this solution, a minor downside is the duplication between the event name and the decorated function name. Or, given that the function name is not important, that this is a little clunky in the same way that the magic attribute and handler method pattern is. A cleaner variation to the solution would be to use the function name as the event name, and to have the decorator take no arguments. However, a larger downside is that the behaviour of decorators within the code reloading framework is undefined and as yet, undetermined.

Another solution is encoding a function name to indicate that it handles a given event. In the system currently in use we already have the __listenevents__ magic method, and of course Python itself has support for private methods (def __Func(self), so this is not necessarily a bad approach to go with. Perhaps something like.
    def _EVENT_PlayerLogin(self):
This is a little ugly, but there are a wealth of possibilities: _event_PlayerLogin, event_PlayerLogin, etc.. This is beginning to look acceptable to me.

An additional use case

The last described solution is all very well, but it is intended to provide for the case where desired events are declared and subscription is taken case of automatically. This will be the most common use case. However, it should still be possible to dynamically register for events.

The ability to dynamically register for events, allows flexible subsystems to be written that build on the underlying event system, by being able to register or unregister for arbitrary events as needed. It is easy enough to add an API to allow this, but it is worth considering how the code reloading system factors into this.

As I do not have a need for this functionality at this time, and it will not affect the design chosen to suit my current needs, I will hold off on designing this for now. But I expect it will make use of the following handy idiom:
    def Register(self, eventName, func):
funcName = func.__name__
obRef = weakref.ref(func.im_self)
self.listeners[eventName].append((funcName, obRef))

def Send(self, eventName, *args, **kwargs):
for funcName, obRef in self.listeners[eventName]:
ob = obRef()
if ob is not None:
func = getattr(ob, funcName)
func(*args, **kwargs)
Conclusion

I will most likely go with the final solution I described. It is the simplest and cleanest from a usage point of view, and this is what is important to me. The event system would take care of enough to make a developer's work simpler and more straightforward, without abstracting away functionality needlessly.

Next post: Sorrows mudlib: An event notification/subscription model, part 2

Thursday, 2 July 2009

LPMuds.net: A word from Lars

Link: A word from Lars

LPMud (and corresponding the MudOS fork of it) is still a remarkable achievement. It is a virtual machine with a scripting language, code reloading, versioned instances of objects and provides an environment for a game to be developed in.

However, the way LPMud was licensed (covered in passing here) meant that commercial use of the driver was a violation. This didn't stop a furor over MUDs that used it commercially. There was various talk over the years about finding all the contributors and relicensing it, but one problem I recall was that no-one was in contact with Lars Pensjö, the author and namesake.

So, it was interesting to see the above linked post by Lars, and to hear his take on LPmud. This doesn't in anyway affect the licensing situation, I seem to recall other contributors, and perhaps a lack of record of who exactly contributed also stood in the way.

Monday, 30 March 2009

PyCon: CCP tools and tips presentation online

Did my presentation today. Although I had practiced the actual speaking part twice, I hadn't practiced running the EVE applications (our systems testing tool and our content development tool). Initially, I had planned to go into some implementation detail, but with only 25 minutes and wanting to give as broad an overview into our use of Python as possible, this wasn't possible.

A technical problem which got in the way was the inability to get what was on my screen output to the projector. Back when I had a Dell, the switch button worked and took care of this. On the work VAIO, it was not happening. Kristjan, who did the other CCP presentation, which followed mine, also had the same problem with his VAIO.

I hope that someone got some value out of it. It was somewhat reassuring to get people coming up after the talk, despite the lack of question time, to ask about various aspects. Someone even managed to check out the open source project I linked to - which was good, but they also pointed out its lack of documentation. I concentrated on getting the code working ready for my presentation and was relieved to get that much done.

The slides are also now uploaded to the conference website.

Saturday, 21 March 2009

PyCon presentation progress report

I previously posted about my PyCon presentation in the post "Making games in Python - Tools and techniques at CCP". This one is a report on the progress in writing it.

A rough draft of my presentation was finished last week but I still needed to edit it and concentrate down all the details. In order to encourage myself to finish it, I scheduled a practice presentation for my coworkers next week. However, two are going to be at GDC, so I did a unprepared really rough preview presentation for them.

While to some degree the presentation was a little confused because of its unedited state, it was definitely worthwhile to get an early chance to do it.

  • It was way too long for the 25 minutes which I have alloted.
  • The implementation details are too confusing and time consuming.
  • Less text and more pictures.
  • Possibilities for more and clearer explanation highlighted.
The new open source implementation of the namespacing and code reloading is getting there. It should be ready to offer as a hand-wavey method of covering the implementation related aspects, given the lack of time to do so in the presentation.

Thursday, 26 February 2009

Implementing code reloading, part 2

This post continues on from Implementing code reloading, part 1.

The biggest limitation when it comes to code reloading is running code.

  • Running code has local variables and external changes to these cannot be made.
  • Running code has bytecode which is in mid-execution and which cannot be replaced until that execution has finished.
Some illustration of these problems will be given below.

Local variables

This will create a function which when run as a Stackless tasklet, blocks in mid-execution on a Stackless channel.
>>> import stackless
>>> c = stackless.channel()
>>> def f():
... a = 1
... b = {}
... c.receive()
Next the tasklet is created and run, leaving it blocked on the channel.
>>> t = stackless.tasklet(f)()
>>> t.run()
The function in mid-execution has a frame encapsulating its running state, like the local variables within that executing function. These variables can be accessed as a dictionary. Sort of.
>>> dir(t)
[..., 'frame', ...]
>>> dir(t.frame)
[..., 'f_locals', ...]
>>> t.frame.f_locals
{'a': 1, 'b': {}}
>>> t.frame.f_locals['a'] = 2
>>> t.frame.f_locals
{'a': 1, 'b': {}}
What this demonstrates is that there is no real local variable dictionary. The one obtained above is actually constructed on request.

The repercussions of this are that code in mid-execution cannot be satisfactorily updated to reflect code reloading changes. That code has to be able to continue executing without error using whatever objects it is holding onto, whatever the approach taken to code reloading is.

Methods

A method is a reference to a function, whether it is obtained from a class or an instance. In the following case, a method is being obtained from a class.
>>> class X:
... def f(self):
... pass
...
>>> X.f
<unbound method X.f>
Methods have attributes which refer to the class (im_class) and function involved (im_func), and possibly also an instance (im_self). Bound methods are taken from instances and have values for all three attributes, whereas unbound methods are taken from classes and do not have an instance. All of these attributes are read only and cannot be changed.
>>> dir(f)
[..., 'im_class', 'im_func', 'im_self']
>>> f.im_class
<class __main__.X at 0x01A1F720>
>>> f.im_class = X
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute
So methods stored as local variables of frames are effectively unchangeable references to the classes and functions they were taken from, both of which can be updated by code reloading. The existing references held in the methods stay in use until the code the frame is associated with, exits.

If the approach taken to code reloading relies on old versions of updated classes not being used after the update, then this is problematic. Whatever approach taken to code reloading, the stale function reference may continue to be used, and programmers need to be aware of that as well.

Wednesday, 25 February 2009

Implementing code reloading, part 1

This post continues on from A custom namespacing system for Python, part 2.

Code reloading

There are many situations where it is useful to be able to update the code an application is using while it is running. Some of the most common are when:

  • A service is being provided by the application and interruption to that service for its users is undesirable.
  • Starting up the application takes an excessive amount of time and modifying its behaviour without restarting it can allow for more productive development.
  • The state which the application maintains is built up after it was started, and the ability to modify behaviour of the application without restarting it allows interaction with the accumulated state.
The obvious way to implement the process of code reloading is to take new versions of objects from a changed file and replace the existing versions which were taken from the file before it changed. This approach will be explored first.

Code reloading through overwriting

With the custom namespacing system previously created, a script file can be loaded and its contents placed into a given namespace.

First a script needs to be loaded.
scriptFile = LoadScript("scripts\example.py", "game")
Next the script is run, placing its contents into the given namespace.
RunScript(scriptFile)
This can easily be hooked up to file change events.
def OnFileChanged(filePath):
scriptFile = LoadScript("scripts\example.py", "game")
RunScript(scriptFile)
A simple overwriting code reloading system can be implemented by repeating this process every time a file changes, which is exactly what would happen if there were actually a file change event hooked up in the manner shown. In response to a file change, the previously created objects from before the change are overwritten by the newly created versions from the freshly changed file.

Overwriting functions

If each time a function is called it is accessed via the namespace, the newest version of the function will be the one which is called. This makes sense, as this is the whole point of the overwriting process which happens on a reload. If a programmer wants to keep calling the same version of the function and not start calling new versions as they get put in place, they need to keep their own reference to the function to call, avoiding use of the namespace.

Overwriting classes

Let's try a few things. To start with, assume that "example.py" provides a base class called BaseObject.
class BaseObject:
def PrintClassName(self):
print self.__class__.__name__ +" (original)"
If there a class is defined, it is likely that at some point that class will be instantiated.
import game
baseObjectBeforeReload = game.BaseObject()
At some point "example.py" is changed, specifically the BaseObject class, triggering a reload. This is the new version of the class:
class BaseObject:
def PrintClassName(self):
print self.__class__.__name__ +" (reloaded)"
Now the namespace entry game.BaseObject will be a new class with the old version overwritten. And since the previously created instance baseObjectBeforeReload was created from the old version of the class, it will still be using that old version of the class.

Executing this code:
baseObjectAfterReload = game.BaseObject()
print baseObjectAfterReload.__class__ is not baseObjectBeforeReload.__class__
baseObjectBeforeReload.PrintClassName()
baseObjectAfterReload.PrintClassName()
Gives this output:
False
"BaseObject (original)"
"BaseObject (reloaded)"
For certain applications, this might be a desirable result. It won't update the behaviour of existing instances which are in use within the application, but it will give a different behaviour for new instances created from the newer classes. If a programmer still wants to create instances from older versions of the class, they can do so by taking a reference to the class from the namespace before a reload has happened and the processing of a changed file has overwritten it.

Limitations to naive class overwriting

However, things get more complicated when inheritance is involved. For the purposes of illustration, here are two classes, BaseObject and its subclass Object.

In the file "example1.py", BaseObject is defined:
class BaseObject:
def TokenFunction(self):
print "TokenFunction called"
In the file "example2.py", Object inherits from BaseObject:
import game

class Object(game.BaseObject):
def TokenFunction(self):
game.BaseObject.TokenFunction(self)
There are two things to note about the Object class:
  • Object.__class__ is a direct reference to the whatever game.BaseObject was when the class was loaded.
  • game.BaseObject in TokenFunction is obtained when the function is executed, this means it is not guaranteed to be the same class as Object.__class__.
When these two classes differ, calling TokenFunction will cause the following error:
TypeError: unbound method TokenFunction() must be called with
BaseObject instance as first argument (got Object instance instead)
This is the primary limitation in the overwriting approach. If this approach is used, then a subclass can never refer to its base class through a namespace reference. It needs to do so through a reference to a version of the base class which won't change. self.__class__.__bases__[0] fits the bill, but using it each time is too unwieldy, and it is easier to store a reference to the version of the class used.
import game
BaseObject = game.BaseObject

class Object(BaseObject):
def TokenFunction(self):
BaseObject.TokenFunction(self)
If a programmer can live with this limitation and does not find the need to keep track of the older references too cumbersome, this form of naive overwriting might be more than sufficient. But to be realistic, this requirement is too impractical to work with.

Overwriting classes "intelligently"

By extending the reloading process it may be possible to remove the need to keep track of those older references. When a class is updated, all the subclasses which inherit the old version need to be updated to be compatible with the new version. The base classes of a subclass can be found in the __bases__ attribute of the subclass. If the reference to the old version of a reloaded class in this attribute is replaced with a reference to the new version, then the above error does not occur.

This can be done in the following manner:
import gc, types
for ob1 in gc.get_referrers(oldBaseObjectClass):
# Class '__bases__' references are stored in a tuple.
if type(ob1) is tuple:
for ob2 in gc.get_referrers(ob1):
if type(ob2) in (types.ClassType, types.TypeType):
if ob2.__bases__ is ob1:
__bases__ = list(ob2.__bases__)
idx = __bases__.index(oldBaseObjectClass)
__bases__[idx] = game.BaseObject
ob2.__bases__ = tuple(__bases__)
But the opposite case is now a problem. If existing references to the old version of the class are stored directly before the reload and used after it, the error can still occur.

This approach can be further extended to cover additional cases, like replacing references to the old class in global dictionaries, but there are references which cannot be replaced. This still leaves the burden on the programmer having to know what cases they need to avoid, in order for this code reloading solution to be workable.

Unit tests illustrating the overwriting approach and general limitations in code reloading approaches can be found here.

What next?

It is useful to know the limitations to code reloading, in order to determine how they apply to a given approach, and how they affect the behaviour of any reloaded code whatever the approach taken.

This post is followed by Implementing code reloading, part 2.

Edited: 2009/02/25, 6:00PM. Rewrote the last couple of paragraphs and linked to the next post.

Friday, 23 January 2009

PyCon 2009: Making games in Python - Tools and techniques at CCP

I will be presenting "Making games in Python - Tools and techniques at CCP" at PyCon this year.

It'll cover a lot of the development techniques we've implemented support for in Python:

  • Our use of code reloading.
  • Our use of unit testing.
  • Our functional/systems testing tools.
  • Our use of wxPython to create authoring tools.
  • And it will of course touch on Stackless.
It was originally planned for my manager, Mark Kalmes, and I to co-present. But he's dropped out of the conference, so I'll be doing the whole thing.

Friday, 7 November 2008

PyCon 2009: CCP related talk proposed

I submitted a talk proposal for PyCon 2009. It's title is "Making games in Python - Tools and techniques at CCP". It's intended to cover all the ways we have customised our framework in order to make working with it more productive, and easier. From the unique ways in which we do our unit testing, to how we use code reloading and more.

Here's hoping it gets accepted! :)

Wednesday, 30 April 2008

Stackless Python MUD framework

I've uploaded my Stackless Python based MUD framework to Google's project hosting:

http://code.google.com/p/sorrows-mudlib/

When I was at university and for a few years afterwards, I joined in the effort to work on an LP MUD based on the MudOS driver. As most of the potential of an 'in-development' MUD is defined by the game systems which have been implemented, and I did most of the programming, I eventually inherited control of the MUD.

After a period of time, I became frustrated by the closed environment MudOS provides and the idea of a straightforward scripting language became appealing. So I rewrote the basic elements of the mudlib in Python. There are only a few toy game related elements present in the code.

Over time I developed a few other projects and they have come to be integrated into this framework as I found the time:

  • Code reloading: As MUD code is changed and the files saved to disk, the game framework detects this and reloads the contents of the files.
  • Stackless-compatible socket module: Asynchronous networking support is hidden away behind the standard socket interface through the use of Stackless Python channels preventing them from influencing framework structure in custom ways.
It also has support for connecting to the Intermud 3 MUD network. Although this isn't 100% working at the moment going into an infinite loop when receiving the initialisation updates from the Intermud router.

Anyway, a friend expressed an interest in possibly using it as the basis for his own MUD experiments so I figured I might as well throw the code out there.

Monday, 18 February 2008

Modifying Python frame locals

Occasionally I find myself wanting to modify the locals dictionary of a Python frame. Ideally it might have been possible by doing the following:

import sys
def f():
v = 1
sys._getframe().f_locals["v"] = 2
return v
But this does not work and v will be unchanged. As far as I can tell, within an acceptable range of effort, it is not possible to modify the local variables of a frame.

One situation where this is useful, is when you are doing code reloading. When you identify a new version of a class, you don't actually want to replace the old version. Instead you want to take the easier approach and update the old version to be the same as the new version.
def UpdateReferences(oldRef, newRef):
currentFrame = sys._getframe()
for referrer in gc.get_referrers(oldRef):
if type(referrer) is types.MethodType:
newRef2 = types.MethodType(newRef, referrer.im_self, referrer.im_class)
UpdateReferences(referrer, newRef2)
elif type(referrer) is types.FrameType:
if referrer is currentFrame:
continue
# Problem case. Local variable replacement..

oldGlobals = existingFile.globals
for k, v in newClass.__dict__.iteritems():
if isinstance(v, types.UnboundMethodType):
f = v.im_func
# Duplicate the function but bound to the original globals dictionary.
g = types.FunctionType(f.func_code, oldGlobals, f.func_name,
f.func_defaults or ())
g.__doc__ = f.__doc__
if f.__dict__ is not None:
g.__dict__ = f.__dict__.copy()
# If the function already existed, update all references to it.
if hasattr(oldClass, k):
UpdateReferences(f, g)
# Inject the updated function on the original class.
setattr(oldClass, k, g)
There are other situations when writing support tools for a custom framework, where in order to allow programmers using it to write straightforward code, the inability to modify the local variables is a roadblock to the simplest solution - or to being able to do it at all.

If anyone knows of an acceptable way to do this, I would be interested in hearing about it.

Saturday, 30 December 2006

Live coding / code reloading for Python

Several months ago there was a spate of interest in live coding with Python. Those who experimented with it reasonably took the approach of continually calling the reload method. However this only worked when code was implemented in a stateless way and how to code within this limitation was covered in detail in the blog posts about it.

I commented on one of the later posts (although my link placement was a little mixed-up) gathering together enough information needed which happened to be publically available and could be used to write the support needed for live coding without the mentioned limitation. To recap that information:

But the general interest in this sort of thing died down and no-one stepped forward to do the work needed. I certainly was not going to do it, as while in theory it would work, it wasn't the approach I would take anyway. Tracking instances so that they can be individually updated seems like much more work than should be required.

A more usable solution would be to update the class itself which would transparently make the changes available to all instances. Though actually implementing this is not as straightforward as one might hope. For instance how functions from classes even unbound are indirectly linked to the class they came from is one of the little hidden surprises of how Python is implemented.

And this "more usable solution" is what I have released, combined with the code from the links above to handle the detection of file changes:
Live coding v 1.0
However there was a design decision made which need to be taken into account. Namely that this is only made possible by using a custom importing solution. All the code which is have automatic code reloading has to be under this solution. Why it was used I will cover after I show how to add a directory containing Python scripts to be made available

This will add a directory of code as importable modules:
import livecoding
cm = livecoding.CodeManager()
cm.AddDirectory("c:\app\server", "applib")

Let's say that 'c:\app' contains the following directories and files:
server\services\networking.py
server\objects\session.py
Where 'networking.py' specifies the class NetworkService and 'session.py' specifies the class Session. Under the algorithm used to map directory contents to an importable namespace, NetworkService would be placed as applib.services.NetworkService and Session would be placed as applib.objects.Session.

So these classes could be imported in the normal manner:
from applib.services import NetworkService
from applib.objects import Session

So why use the custom importing solution? Well, it makes updating loaded code with changes easier because as the library controls the importing it knows what to update and how. But why not look into getting a similar system working with the standard module system? Not interested, sorry. My fellow author and I have worked a lot with custom importing systems and found them to be much easier to work with than the standard module system. And over time we have come to prefer the system which this library implements.

I also cobbled together another library filechanges which comes as part of the download or can also be obtained from the SVN archive. This is just a collection of the file change detection code found in the links I originally gathered above. The livecoding library can be told to use this to provide built in file change detection.
import livecoding
cm = livecoding.CodeManager(detectChanges=True)
cm.AddDirectory("c:\app\server", "applib")

Which completes the collection of functionality which makes up the v1.0 release of this library. However there is still work remaining to do. There is the incomplete override feature, clean up needed regarding custom methods of handling the file update events and more methods of file change detection other than the only one which currently works (the cross-platform one).