Hi All RexDevs,

I'm working on VNC (remote desktop) integration for Tundra.  One of
the goals is to have this feature as an addon and not built into
Tundra's core under "pymodules".  I had a look at pymodules,
autoload.py and default.ini; looks like a good system that can easily
be adapted for addons.  Whatever interface we have for enabling/
disabling addons, it can simply comment or uncomment all entries in
the addon .ini file.

in autoload.py we only need to change to also read from the users
local settings.
def read_inis():
    dirs = []
    dirs.append( os.path.split(os.path.abspath(__file__))[0] )
    if sys.platform in 'linux2 darwin'.split():
        dirs.append( os.path.join(os.environ['HOME'],'.rex-addons' ) )
    elif sys.platform == 'win32': dirs.append( how do you get users
home in windows? )
    for thisdir in dirs:
         for inifile in glob(os.path.join(thisdir, "*.ini")): ...

I see that autoload.py:48 inits the class as modinst and appends it to
circuitsmanager.  I assume then the class must be a subclass of
circuits.Component.  This is not something that should not always be
imposed, some addons may not use circuits and may run via a subprocess
or some other method.

XML Addon Format:
The simplest format i can think of is something like below.  This
example and implementation requires things are packaged into tar
files, python contains a zip unpacker but i didn't implement that.  I
think its best to allow addons to overwrite others, and have no forced
sub directory per module, this encourages addons to share parts,
extend others, even bug fix others.  It could become a problem if
packagers use names already in use by other addons, but hopefully all
the addons will be listed in some central place on the web for
download, and addon creators can check there before packaging.

<addon platforms="all" author="name" email="" version=""
ini="myaddon.ini">
        <archive url="http://...some.tar.gz"; path="." extract="True" md5="">
        <library name="" about="" required="True">
                <linux32 url="http://..."; path=".">
                <windows32 url="http://..."; path=".">
                <source url="github..." notes="works on all platforms, just need
help compiling for others">
        </library
</addon>

"addon" contains "platforms", in case an addon will only work on a
given platform, it can be stated here, and if the user tries to
install the addon on an unsupported platform, a warning can be shown.
Should "name" and "email" be required?

"archive" can be a zip or tar that is automatically extracted to the
users home settings ".rex-addons".  If it should not be automatically
extracted (say if the addon wants to have some extra data kept in an
archive), then setting "extract" to false stops the addon manager from
extracting it.

"library" contains [linux32, linux64, windows32, windows64, osx-intel,
osx-ppc], the addon manager will know what OS and bits its running on,
and fetch only the required (.dll, .so, .dynlib) it needs.  "source"
is optional, and is a link to the source code used to build the shared
library.  This can be useful in the case the user is also a programmer
they may prefer to build from source, or in the case the packager did
not build yet for that platform.  In the second case, the packager may
not have a way to build for all platforms, so it helps streamline
communication among developers - nobody needs to ask packager where is
latest source and if he needs help building it for platformX - they
can build it and then email the packager to help them out.


#Basic Implementation:
import xml.dom.minidom
import tarfile, urllib, hashlib
REXADDONS = '/tmp/addontest'
IS64BIT = (sys.maxint == 9223372036854775807L)

def download( url, md5=None, path=None ):
        assert not path.startswith('../')       # do not allow outside of 
REXADDONS
        data = urllib.urlopen( url ).read()
        if md5: assert hashlib.md5sum( data ).hexdigest() == md5
        tmp = '/tmp/%s' %os.path.split( url )[-1]
        f = open( tmp, 'wb' ); f.write( data ); f.close()
        if url.endswith('.tar.gz') or url.endswith('.tgz') or
url.endswith('.tar.bz2') or url.endswith('.tar'):
                tar = tarfile.TarFile( tmp )
                if path: tar.extractall( path=os.path.join(REXADDONS,path) )
                else: tar.extractall( path=REXADDONS )

def install_addon( url ):
        doc = xml.dom.minidom.parse( url )
        platforms = doc.documentElement.getAttribute('platforms')
        if not platforms: print('warning: this addon did not describe what
platforms it can run on')
        elif platforms == 'all': print('addon runs on all platforms')
        else:
                print('addon only supports the following platforms:')
                for plat in platforms.split(','): print( plat )

        iniFile = doc.documentElement.getAttribute('ini-file')
        assert iniFile

        for ar in doc.getElementsByTagName('archive'):
                url = ar.getAttribute('url'); download( url,
md5=ar.getAttribute('md5'), path=ar.getAttribute('path') )
        for library in doc.getElementsByTagName('library'):
                libs = []
                if sys.platform == 'linux2' and IS64BIT: libs +=
library.getElementsByTagName('linux64')
                elif sys.platform == 'linux2' and not IS64BIT: libs +=
library.getElementsByTagName('linux32')
                elif sys.platform.startswith('win') and IS64BIT: libs +=
library.getElementsByTagName('windows64')
                elif sys.platform.startswith('win') and not IS64BIT: libs +=
library.getElementsByTagName('windows32')
                elif sys.platform.startswith('darwin') and is IS64BIT: libs +=
library.getElementsByTagName('osx-intel')
                ## how can we know if its OSX PPC or Intel?
                ## support other platforms?

                if not libs:
                        if library.getAttribute('required')=='True': 
print('error: this
library is required %s' %library.getAttribute('name'))
                        print('no precompiled library for your OS')
                        sources = library.getElementsByTagName('source')
                        for src in sources:
                                print('source is available here:')
                                print( src.getAttribute('url') )
                                print( src.getAttribute('notes') )

                for lib in libs:
                        url = lib.getAttribute('url')
                        download( url, md5=lib.getAttribute('md5'),
path=lib.getAttribute('path') )

        assert os.path.isfile( os.path.join(REXADDONS, iniFIle) )
        return iniFile  # some installer-manager needs to keep track of ini-
files and addon.xmls so it can enable/disable them

-- 
http://groups.google.com/group/realxtend
http://www.realxtend.org

Reply via email to