예제 #1
0
    def accept(self, source):
        val = source.pop_word(self)
        pos = val.find('/')
        if pos < 0:
            raise CommandError('Not of form package/resource: ' + val)

        res = val[pos + 1:]
        val = val[:pos]

        try:
            pinfo.parse_resource_name(res)
        except:
            raise CommandError('Invalid resource name: ' + res)

        try:
            (pkg, vers) = pinfo.parse_package_version_spec(val)
        except:
            raise CommandError('Invalid package name: ' + val)

        return ((pkg, vers), res)
예제 #2
0
    def attrify_filename(self, pkg, mod, wholekey, res, filename):
        """attrify_filename(pkg, mod, wholekey, res, filename) -> None

        Given a filename, create a File representing it, and store the
        File in the module at a location defined by wholekey. Submodules
        are created as necessary. The res argument is the Resource
        object associated with wholekey.

        The filename must be in universal format: relative to the package
        root, and written with forward slashes, not backslashes.

        (If the filename is invalid or unsafe, ValueError is raised.
        However, this does not check whether the file exists.)
        """

        file = pkg.get_file(filename)
                
        keyls = parse_resource_name(wholekey)
        attr = keyls.pop()
        for key in keyls:
            submod = getattr(mod, key, None)
            if (submod is None):
                # Create an empty submodule.
                (fl, pathname, desc) = imp.find_module('emptymodule', boopak.__path__)
                try:
                    submod = imp.load_module(mod.__name__+'.'+key,
                        fl, pathname, desc)
                finally:
                    # Clean up.
                    if (fl):
                        fl.close()
                setattr(mod, key, submod)
                
            if (type(submod) != types.ModuleType):
                raise ValueError('resource key based on non-module: ' + wholekey)
            if (mod.__name__+'.'+key != submod.__name__):
                raise ValueError('resource key based on imported module: ' + wholekey)
            mod = submod

        # We've drilled down so that mod is the next-to-last element
        # of the original wholekey.
        
        setattr(mod, attr, file)
        file.metadata = res
        
        # Set properties analogous to a statically-declared object. This
        # will help with find_item_resources() later on.
        file.__module__ = mod.__name__
        file.__name__ = attr
예제 #3
0
    def test_parse_resource_name(self):
        valid_list = [
            ('hello', ['hello']),
            ('Hello.FOO.X0', ['Hello', 'FOO', 'X0']),
            ('X', ['X']),
            ('h.e.l.l.o', ['h', 'e', 'l', 'l', 'o']),
            ('x_00t_99', ['x_00t_99']),
            ('t0.t1', ['t0', 't1']),
            ('_._005_.a', ['_', '_005_', 'a']),
        ]
        invalid_list = [
            '',
            ' ',
            '.',
            'a.',
            '.b',
            '.c.',
            'd..e',
            '..',
            'x ',
            ' y',
            'a b',
            'a. b',
            'a .b',
            '0',
            '0x',
            'a.0',
            'x.y.9z',
            'a,b',
            'a-b',
            'a+b',
            'a/b',
            'a\\b',
        ]

        for (name, result) in valid_list:
            res = parse_resource_name(name)
            self.assertEqual(res, result)

        for name in invalid_list:
            self.assertRaises(ValueError, parse_resource_name, name)
예제 #4
0
    def import_package_content(self, pkg):
        """import_package_content(pkg) -> None

        Import the package's content, if it hasn't already been imported.

        Warning: this method imports Python source code from the package
        directory, which means it *executes* Python source code from the
        package directory. Do not call this on untrusted packages.

        A sound-player will have to call this, but a package manager
        should not.
        """

        if (not self.importing_ok):
            raise Exception('this loader may not import package data!')
        if (not (pkg.content is None)):
            return
        if (pkg.import_in_progress):
            raise Exception('package imported while import is in progress: ' + pkg.name)

        attrify_resources = False
        map_resources = False
        
        maincode = pkg.metadata.get_one('boodler.main')
        if (not maincode):
            attrify_resources = True
            (file, pathname, desc) = imp.find_module('emptymodule', boopak.__path__)
        else:
            map_resources = True
            (file, pathname, desc) = imp.find_module(maincode, [pkg.dir])
            
        if (not desc[0] in ['', '.py', '.pyc']):
            if (file):
                file.close()
            raise PackageLoadError(pkg.name,
                'module must be .py or .pyc: ' + pathname)

        # Imports can occur recursively, so we always hold on to the previous
        # value and restore it afterward.

        previously_importing = self.currently_importing
        self.currently_importing = pkg
        pkg.import_in_progress = True
        
        try:
            mod = imp.load_module(pkg.encoded_name, file, pathname, desc)
        finally:
            # Clean up.
            if (file):
                file.close()
            pkg.import_in_progress = False
            checkpkg = self.currently_importing
            self.currently_importing = previously_importing
            if (checkpkg != pkg):
                raise Exception('import stack unstable: ' + pkg.name)

        if (attrify_resources):
            for res in pkg.resources.resources():
                filename = res.get_one('boodler.filename')
                if (filename):
                    self.attrify_filename(pkg, mod, res.key, res, filename)

        if (map_resources):
            # Look for declarations in the module which are named in
            # the resources map. Cache the mapping from the declaration
            # to the resource object.
            for res in pkg.resources.resources():
                keyls = parse_resource_name(res.key)
                submod = mod
                for key in keyls:
                    submod = getattr(submod, key, None)
                    if (submod is None):
                        break
                if (not (submod is None)):
                    pkg.content_info[submod] = res
        
        # The import is complete.
        self.module_info[mod] = pkg
        pkg.content = mod
예제 #5
0
    def import_package_content(self, pkg):
        """import_package_content(pkg) -> None

        Import the package's content, if it hasn't already been imported.

        Warning: this method imports Python source code from the package
        directory, which means it *executes* Python source code from the
        package directory. Do not call this on untrusted packages.

        A sound-player will have to call this, but a package manager
        should not.
        """

        if not self.importing_ok:
            raise Exception('this loader may not import package data!')

        if pkg.content is not None:
            return

        if pkg.import_in_progress:
            raise Exception('package imported while import is in progress: ' + pkg.name)

        attrify_resources = False
        map_resources = False

        maincode = pkg.metadata.get_one('boodler.main')

        # Imports can occur recursively, so we always hold on to the previous
        # value and restore it afterward.

        previously_importing = self.currently_importing
        self.currently_importing = pkg
        pkg.import_in_progress = True

        try:
            if not maincode:
                attrify_resources = True
                mod = load_module(pkg.encoded_name, 'emptymodule', boopak.__path__[0])
            else:
                map_resources = True
                mod = load_module(pkg.encoded_name, maincode, pkg.dir)
        finally:
            pkg.import_in_progress = False
            checkpkg = self.currently_importing

            self.currently_importing = previously_importing

            if checkpkg != pkg:
                raise Exception('import stack unstable: ' + pkg.name)

        if attrify_resources:
            for res in pkg.resources.resources():
                filename = res.get_one('boodler.filename')

                if filename:
                    self.attrify_filename(pkg, mod, res.key, res, filename)

        if map_resources:
            # Look for declarations in the module which are named in
            # the resources map. Cache the mapping from the declaration
            # to the resource object.
            for res in pkg.resources.resources():
                keyls = parse_resource_name(res.key)
                submod = mod

                for key in keyls:
                    submod = getattr(submod, key, None)

                    if submod is None:
                        break

                if submod is not None:
                    pkg.content_info[submod] = res

        # The import is complete.
        self.module_info[mod] = pkg

        return mod