DecodeImporter

 avatar
unknown
python
3 years ago
3.2 kB
8
Indexable
#coding=utf-8

import os
import sys
import imp
import base64

EXT = '.b64'


class Base64Importer(object):
    #---------------------------------------------------------------------------
    def __init__(self, root_package_path):
        self.__modules_info = self.__collect_modules_info(root_package_path)
        self.__python_version = sys.version_info

    #---------------------------------------------------------------------------
    def find_module(self, fullname, path=None):
        if fullname in self.__modules_info:
            return self
        return None

    #---------------------------------------------------------------------------
    def load_module(self, fullname):
        if not fullname in self.__modules_info:
            raise ImportError(fullname)

        imp.acquire_lock()

        try:
            mod = sys.modules.setdefault(fullname, imp.new_module(fullname))

            mod.__file__ = "<{}>".format(self.__class__.__name__)
            mod.__loader__ = self

            if self.is_package(fullname):
                mod.__path__ = []
                mod.__package__ = fullname
            else:
                mod.__package__ = fullname.rpartition('.')[0]

            src = self.get_source(fullname)

            try:
                exec(src) in mod.__dict__
            except Exception as e:
                del sys.modules[fullname]
                raise ImportError(fullname)
        finally:
            imp.release_lock()

        return mod

    #---------------------------------------------------------------------------
    def is_package(self, fullname):
        return self.__modules_info[fullname]['ispackage']

    #---------------------------------------------------------------------------
    def get_source(self, fullname):
        filename = self.__modules_info[fullname]['filename']

        try:
            with open(filename, 'rb') as ifile:
                if self.__python_version > (3, 8):
                    src = base64.decodebytes(ifile.read())
                else:
                    src = base64.decodestring(ifile.read())
        except IOError:
            src = ''

        return src.decode('utf-8')

    #---------------------------------------------------------------------------
    def __collect_modules_info(self, root_package_path):
        modules = {}

        p = os.path.abspath(root_package_path)
        dir_name = os.path.dirname(p) + os.sep

        for root, _, files in os.walk(p):
            filename = os.path.join(root, '__init__' + EXT)
            p_fullname = root.rpartition(dir_name)[2].replace(os.sep, '.')

            modules[p_fullname] = {
                'filename': filename,
                'ispackage': True
            }

            for f in files:
                if not f.endswith(EXT):
                    continue

                filename = os.path.join(root, f)
                fullname = '.'.join([p_fullname, os.path.splitext(f)[0]])

                modules[fullname] = {
                    'filename': filename,
                    'ispackage': False
                }

        modules = dict(sorted(modules.items(), key=lambda item: item[0]))
        return modules
Editor is loading...