I plan on writing a server that is purely maths (made in code) anyway. So it wouldn't be too different writing the server purely in python.
Maybe you missed my point, but I meant that if you're going to go through the trouble of duplicating all of Construct's helpful events and what not into python, why not just write everything from scratch to begin with?
The method of thinking you're taking will lead to road blocks down the road, primarily in the form of physics/extrapolation/interpolation. If the server-client movement code, for example, is not identical, your simulation will be off if you're using any kind of client-server architecture.
this way we don't end up with a huge list (because the list re-uses empty entries). I assume this is the best way to do it?
Your "list" will only ever be the size of the amount of people connected. If you're worried going out of range on your indexing, perhaps you're not picturing it right in your mind.
First, you can use an ID generated by a storage medium (SQL, for example). Bear in mind the max int size within python is a signed long (for most distributions)... +/- 2,147,483,647. Try to imagine how long it would take to exceed that. At 10,000 connections a day, which ain't bad for most websites, that's 214,748 days until that number fills up. Or 588 years. Of course a malicious user who writes a connect/disconnect bot will make your server throw an exception rapidly.
Secondly, and probably more realistically, you should be using a guid. In which case, the concern isn't really valid to begin with. If you're going to send 4-8 bytes anyway, it may as well be a unique identifier. This might lend some security as well, if you use the first method and only that, objects will always be the same ID, which could give sniffers an advantage (hard to imagine how, but scripting would be much easier).
You might find a combination of the two to be the most appealing approach, though.
How do you do this in python, or is there a more appropriate way?
Heh. You may be a little over your head at this point, no?
Otherwise, in your class's add method, you could simply increment a private index value each time there's a connection. Off the top of my head... index = len(list)+1 would probably suffice.
- also, wouldn't each client need a unique "ID" so you can send messages directly to certain clients from the server?
Well, PodSixNet is a connection based library... You'd just send directly to their connection. You might organize that into a set of containers (channels, for example), in which case, if you just want to talk directly to clients you could keep a "master" copy container (dictionary) for convenience. If I recall, that's how the author of PodSix does it, although he uses WeakRef (which is probably cleaner at the end of the day).
Try not to overthink it too much, in most cases, you'll be sending a response to the client directly so you'll know which channel to reply to at the moment of receiving their request (try to think of an event-based networking system -- this is how WoW does it).
2) I couldn't quite work out how channels work. Can we send messages to all players on a channel? And can channel names be strings? Surely its important to ensure that we can send messages to certain groups of clients, but not everyone connected?
From a limited amount of looking at PodSixNet's innards, it does not do client channeling for you. I'm not familiar with the tutorial you're referencing, but client channeling is fairly easy to pull off. Use a dictionary (or some variety) if you wish to look them up by a string (probably pointing to a custom class you make which keeps references to the clients in said channel). This is where the various smart pointer classes in Python will be handy, since likely, you'll have references in multiple containers. Again, this all depends on how you design the data structures of your program.