pkg_resources fails on Google App Engine

Issue #73 resolved
Attila Oláh
created an issue

This is from jinja2.loaders.PackageLoader:

{{{ from pkg_resources import DefaultProvider, ResourceManager, \ get_provider }}}

It uses pkg_resources to determine the location of the directory containing a given package. Since distribute's flavor of pkg_resources wants to import mkdir, it raises an ImportError on Google App Engine, since the deployment environment lives on a "read-only filesystem" (the application has no write access).

However, jinja2 only wants to use pkg_resources in read-only mode, so a try/except would work...

Of course, jinja2.loaders.FileSystemLoader is a possible workaround. Yet it would be nice to support Google App Engine. Or am I the only one using it? :)

Comments (5)

  1. Tarek Ziadé repo owner

    I am going to change pkg_resources so "import mkdir" is protected. If ResourceManager.get_cache_path is called, and it tries to create a directory, it will raise an IOError. That will prevent "import pkg_resources" to break on GAE.

    Next, get_resource_filename() returns a real path for the API consumer to be able to ope and read it, so it uncompress the file in a temp dir.

    That's a problem in GAE indeed, where it should be fully done in memory, meaning that ZipProvider should implement "get_resource_string" and "get_resource_stream" as well, and do the whome work in memory.

    Can I see how Jinja uses pkg_resources here ? That will be our use case in the tests to fix this.


  2. Attila Oláh reporter

    Jinja2 uses pkg_resources in two places: (not a big issue here):

        __version__ = __import__('pkg_resources') \
        __version__ = 'unknown'

    class PackageLoader(BaseLoader):
        def __init__(self, package_name, package_path='templates',
            from pkg_resources import DefaultProvider, ResourceManager, \
            provider = get_provider(package_name)
            self.encoding = encoding
            self.manager = ResourceManager()
            self.filesystem_bound = isinstance(provider, DefaultProvider)
            self.provider = provider
            self.package_path = package_path

    Here's the complete file:

    PS: I'll check if it works with the commit you've just made.

  3. Log in to comment