view paint/package.py @ 12:ceb8c69a16f3

dependencies should consume info
author Jeff Hammel <jhammel@mozilla.com>
date Fri, 24 Feb 2012 15:21:28 -0800
parents c41a946d34af
children 0dd1f8f83be2
line wrap: on
line source

"""
package model for python PAckage INTrospection
"""

import os
import shutil
import tarfile
import tempfile
import urllib2
import utils

__all__ = ['Package']

class Package(object):
    # XXX much of this is generic resource stuff and should be split off

    def __init__(self, src):
        self.src = src
        self._tmppath = None

    def path(self):
        """filesystem path to package"""

        # return cached copy if it exists
        if self._tmppath:
            return self._tmppath

        # fetch from the web if a URL
        tmpfile = None
        src = self.src
        if utils.isURL(self.src):
            tmpfile = src = self.fetch()

        # unpack if an archive
        if self.is_archive(src):
            try:
                self.unpack(src)
            finally:
                if tmpfile:
                    os.remove(tmpfile)
            return self._tmppath

        return self.src

    def fetch(self):
        """fetch from remote source to a temporary file"""
        fd, filename = tempfile.mkstemp()
        resource = urllib2.urlopen(self.src)
        os.write(fd, resource.read())
        os.close(fd)
        return filename

    def unpack(self, archive):
        """unpack the archive to a temporary destination"""
        # TODO: should handle zipfile additionally at least
        # Ideally, this would be pluggable, etc
        assert tarfile.is_tarfile(archive), "%s is not an archive" % self.src
        tf = tarfile.TarFile.open(archive)
        self._tmppath = tempfile.mkdtemp()
        tf.extractall(path=self._tmppath)

    def is_archive(self, path):
        """returns if the filesystem path is an archive"""
        # TODO: should handle zipfile additionally at least
        # Ideally, this would be pluggable, etc
        return tarfile.is_tarfile(path)

    def cleanup(self):
        if self._tmppath:
            shutil.rmtree(self._tmppath)
        self._tmppath = None

    __del__ = cleanup

    def info(self):
        """return info dictionary for package"""
        path = self.path()
        assert os.path.exists(os.path.join(path, 'setup.py'))

    def dependencies(self):
        info = self.info()