I've been working on pyinsim 3.0.0 recently, which is a new version of pyinsim designed to support Python 3.0. I decided to take this opportunity to fix a bunch of issues I had with the previous version of library, and also add some new features.
I'm not sure how/if I'm going to integrate the new version with the existing CodePlex repository, so in the mean time I created a new Mercurial repository on my BitBucket account. You can view, clone or download the development version of pyinsim 3.0.0 here:
https://bitbucket.org/alexmcbride/pyinsim
The biggest change to pyinsim, aside from some changes to the API, is that all strings are now unicode by default. pyinsim now automatically converts LFS encoded strings to unicode and back again when sending or receiving packets. In Python 3.0 all strings are unicode, and while I messed around with using the new bytes type to represent LFS encoded strings, this created a lot of issues and made programming pyinsim apps much more complex.
One of the primary goals of pyinsim is to be as simple to use as possible, so I took the decision to just make all strings unicode and do the encoding/decoding on the fly, (hopefully) without you noticing. Obviously this means that packing and unpacking packets is slightly slower than before, as each character in each string needs to be converted to the correct type, but in my tests any additional latency was barely noticeable.
Right now you can actually switch between unicode and ASCII strings (and even reimplement the string encoding/decoding stuff) by giving pyinsim a new StrFactory object. There are two default StrFactory objects in pyinsim, AsciiStrFactory and UniStrFactory, and you can change between them like this:
import pyinsim
# Set the string factory to ASCII.
pyinsim.str_factory = pyinsim.AsciiStrFactory()
# Set the string factory to Unicode.
pyinsim.str_factory = pyinsim.UniStrFactory()
# TODO: Write normal pyinsim code here.
By default the library uses the UniStrFactory() to handle strings, and this is intended to be the 'proper' way to handle strings from now on. You shouldn't need to think about all this, as I said it should work without you needing to worry about it. I have a few ideas for how to speed up the string conversions in the future, but right now I'm going with the simple way of doing things. All this StrFactory stuff is kinda interesting, but I don't know if I'll keep it around in the final version. I reminded of the quote about how any choice you give the consumer of your API is a choice you were unwilling to make yourself.
I have also made the API in general a little more verbose, as finally I think that a combination of succinctness and verbosity is the best balance. Too much of the former makes the library hard to understand, too much of the later makes it hard to program against. In pyinsim 2.0 I tried the make the API as succinct as possible, but in retrospect that was a mistake, and a lot of the functions ended up with confusing names. I have now changed how you init the InSim system, and also in how you bind events, as well as some other stuff in order to correct this.
Instead of explaining every change here is a quick example of some new pyinsim 3.0.0 code. This example is of a simple 'sniffer' style app, that dumps the contents of each packet received to the console (very useful for debugging).
#!/usr/bin/env python
#coding=utf-8
# Import pyinsim package.
import pyinsim
# Function called whenever a packet is received.
def packet(insim, pack):
# Dump packet contents to output.
print(vars(pack))
# Initialize InSim.
insim = pyinsim.insim_init('127.0.0.1', 29999, Admin='')
# Bind function callback for all packet events.
insim.bind_event(pyinsim.EVT_PACKET, packet)
# Send MST packet to LFS.
insim.send(pyinsim.ISP_MST, Msg='Hello, InSim!')
# Run the pyinsim event loop.
pyinsim.run()
As you can see the insim_init function is new, as well as the bind_event function (their related functions (e.g. outsim_init, bind_event etc..) have been renamed as well). Hopefully it should all be self-explanatory really, and you should look at the dev source code (mainly core.py and helper.py) to see the changes in full. I will of course try to document every change before the final version, but currently everything is still in flux. The library works much as it did before, it's just that some of the function and class names are slightly different. Better. Better?
There are countless improvements to the code overall, most of the library has been rewritten, and I've figured out better ways to handle lots of stuff such as the write/read socket code. Even though this new version of pyinsim does more (such as decoding unicode strings on the fly!), it is much more efficient in other areas. That being said, every change is also an opportunity for a new bug to creep in, so I anticipate lots of issues and errors to find.
Anyway, if you're an experienced pyinsim programmer, feel free to give it a try and come back to me with your comments and suggestions.
Thanks!