Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
verifier.py307 linesDownload Raw Back to cffi
1#2# DEPRECATED: implementation for ffi.verify()3#4import sys, os, binascii, shutil, io5from . import __version_verifier_modules__6from . import ffiplatform7from .error import VerificationError8 9if sys.version_info >= (3, 3):10    import importlib.machinery11    def _extension_suffixes():12        return importlib.machinery.EXTENSION_SUFFIXES[:]13else:14    import imp15    def _extension_suffixes():16        return [suffix for suffix, _, type in imp.get_suffixes()17                if type == imp.C_EXTENSION]18 19 20if sys.version_info >= (3,):21    NativeIO = io.StringIO22else:23    class NativeIO(io.BytesIO):24        def write(self, s):25            if isinstance(s, unicode):26                s = s.encode('ascii')27            super(NativeIO, self).write(s)28 29 30class Verifier(object):31 32    def __init__(self, ffi, preamble, tmpdir=None, modulename=None,33                 ext_package=None, tag='', force_generic_engine=False,34                 source_extension='.c', flags=None, relative_to=None, **kwds):35        if ffi._parser._uses_new_feature:36            raise VerificationError(37                "feature not supported with ffi.verify(), but only "38                "with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,))39        self.ffi = ffi40        self.preamble = preamble41        if not modulename:42            flattened_kwds = ffiplatform.flatten(kwds)43        vengine_class = _locate_engine_class(ffi, force_generic_engine)44        self._vengine = vengine_class(self)45        self._vengine.patch_extension_kwds(kwds)46        self.flags = flags47        self.kwds = self.make_relative_to(kwds, relative_to)48        #49        if modulename:50            if tag:51                raise TypeError("can't specify both 'modulename' and 'tag'")52        else:53            key = '\x00'.join(['%d.%d' % sys.version_info[:2],54                               __version_verifier_modules__,55                               preamble, flattened_kwds] +56                              ffi._cdefsources)57            if sys.version_info >= (3,):58                key = key.encode('utf-8')59            k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)60            k1 = k1.lstrip('0x').rstrip('L')61            k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)62            k2 = k2.lstrip('0').rstrip('L')63            modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key,64                                              k1, k2)65        suffix = _get_so_suffixes()[0]66        self.tmpdir = tmpdir or _caller_dir_pycache()67        self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension)68        self.modulefilename = os.path.join(self.tmpdir, modulename + suffix)69        self.ext_package = ext_package70        self._has_source = False71        self._has_module = False72 73    def write_source(self, file=None):74        """Write the C source code.  It is produced in 'self.sourcefilename',75        which can be tweaked beforehand."""76        with self.ffi._lock:77            if self._has_source and file is None:78                raise VerificationError(79                    "source code already written")80            self._write_source(file)81 82    def compile_module(self):83        """Write the C source code (if not done already) and compile it.84        This produces a dynamic link library in 'self.modulefilename'."""85        with self.ffi._lock:86            if self._has_module:87                raise VerificationError("module already compiled")88            if not self._has_source:89                self._write_source()90            self._compile_module()91 92    def load_library(self):93        """Get a C module from this Verifier instance.94        Returns an instance of a FFILibrary class that behaves like the95        objects returned by ffi.dlopen(), but that delegates all96        operations to the C module.  If necessary, the C code is written97        and compiled first.98        """99        with self.ffi._lock:100            if not self._has_module:101                self._locate_module()102                if not self._has_module:103                    if not self._has_source:104                        self._write_source()105                    self._compile_module()106            return self._load_library()107 108    def get_module_name(self):109        basename = os.path.basename(self.modulefilename)110        # kill both the .so extension and the other .'s, as introduced111        # by Python 3: 'basename.cpython-33m.so'112        basename = basename.split('.', 1)[0]113        # and the _d added in Python 2 debug builds --- but try to be114        # conservative and not kill a legitimate _d115        if basename.endswith('_d') and hasattr(sys, 'gettotalrefcount'):116            basename = basename[:-2]117        return basename118 119    def get_extension(self):120        if not self._has_source:121            with self.ffi._lock:122                if not self._has_source:123                    self._write_source()124        sourcename = ffiplatform.maybe_relative_path(self.sourcefilename)125        modname = self.get_module_name()126        return ffiplatform.get_extension(sourcename, modname, **self.kwds)127 128    def generates_python_module(self):129        return self._vengine._gen_python_module130 131    def make_relative_to(self, kwds, relative_to):132        if relative_to and os.path.dirname(relative_to):133            dirname = os.path.dirname(relative_to)134            kwds = kwds.copy()135            for key in ffiplatform.LIST_OF_FILE_NAMES:136                if key in kwds:137                    lst = kwds[key]138                    if not isinstance(lst, (list, tuple)):139                        raise TypeError("keyword '%s' should be a list or tuple"140                                        % (key,))141                    lst = [os.path.join(dirname, fn) for fn in lst]142                    kwds[key] = lst143        return kwds144 145    # ----------146 147    def _locate_module(self):148        if not os.path.isfile(self.modulefilename):149            if self.ext_package:150                try:151                    pkg = __import__(self.ext_package, None, None, ['__doc__'])152                except ImportError:153                    return      # cannot import the package itself, give up154                    # (e.g. it might be called differently before installation)155                path = pkg.__path__156            else:157                path = None158            filename = self._vengine.find_module(self.get_module_name(), path,159                                                 _get_so_suffixes())160            if filename is None:161                return162            self.modulefilename = filename163        self._vengine.collect_types()164        self._has_module = True165 166    def _write_source_to(self, file):167        self._vengine._f = file168        try:169            self._vengine.write_source_to_f()170        finally:171            del self._vengine._f172 173    def _write_source(self, file=None):174        if file is not None:175            self._write_source_to(file)176        else:177            # Write our source file to an in memory file.178            f = NativeIO()179            self._write_source_to(f)180            source_data = f.getvalue()181 182            # Determine if this matches the current file183            if os.path.exists(self.sourcefilename):184                with open(self.sourcefilename, "r") as fp:185                    needs_written = not (fp.read() == source_data)186            else:187                needs_written = True188 189            # Actually write the file out if it doesn't match190            if needs_written:191                _ensure_dir(self.sourcefilename)192                with open(self.sourcefilename, "w") as fp:193                    fp.write(source_data)194 195            # Set this flag196            self._has_source = True197 198    def _compile_module(self):199        # compile this C source200        tmpdir = os.path.dirname(self.sourcefilename)201        outputfilename = ffiplatform.compile(tmpdir, self.get_extension())202        try:203            same = ffiplatform.samefile(outputfilename, self.modulefilename)204        except OSError:205            same = False206        if not same:207            _ensure_dir(self.modulefilename)208            shutil.move(outputfilename, self.modulefilename)209        self._has_module = True210 211    def _load_library(self):212        assert self._has_module213        if self.flags is not None:214            return self._vengine.load_library(self.flags)215        else:216            return self._vengine.load_library()217 218# ____________________________________________________________219 220_FORCE_GENERIC_ENGINE = False      # for tests221 222def _locate_engine_class(ffi, force_generic_engine):223    if _FORCE_GENERIC_ENGINE:224        force_generic_engine = True225    if not force_generic_engine:226        if '__pypy__' in sys.builtin_module_names:227            force_generic_engine = True228        else:229            try:230                import _cffi_backend231            except ImportError:232                _cffi_backend = '?'233            if ffi._backend is not _cffi_backend:234                force_generic_engine = True235    if force_generic_engine:236        from . import vengine_gen237        return vengine_gen.VGenericEngine238    else:239        from . import vengine_cpy240        return vengine_cpy.VCPythonEngine241 242# ____________________________________________________________243 244_TMPDIR = None245 246def _caller_dir_pycache():247    if _TMPDIR:248        return _TMPDIR249    result = os.environ.get('CFFI_TMPDIR')250    if result:251        return result252    filename = sys._getframe(2).f_code.co_filename253    return os.path.abspath(os.path.join(os.path.dirname(filename),254                           '__pycache__'))255 256def set_tmpdir(dirname):257    """Set the temporary directory to use instead of __pycache__."""258    global _TMPDIR259    _TMPDIR = dirname260 261def cleanup_tmpdir(tmpdir=None, keep_so=False):262    """Clean up the temporary directory by removing all files in it263    called `_cffi_*.{c,so}` as well as the `build` subdirectory."""264    tmpdir = tmpdir or _caller_dir_pycache()265    try:266        filelist = os.listdir(tmpdir)267    except OSError:268        return269    if keep_so:270        suffix = '.c'   # only remove .c files271    else:272        suffix = _get_so_suffixes()[0].lower()273    for fn in filelist:274        if fn.lower().startswith('_cffi_') and (275                fn.lower().endswith(suffix) or fn.lower().endswith('.c')):276            try:277                os.unlink(os.path.join(tmpdir, fn))278            except OSError:279                pass280    clean_dir = [os.path.join(tmpdir, 'build')]281    for dir in clean_dir:282        try:283            for fn in os.listdir(dir):284                fn = os.path.join(dir, fn)285                if os.path.isdir(fn):286                    clean_dir.append(fn)287                else:288                    os.unlink(fn)289        except OSError:290            pass291 292def _get_so_suffixes():293    suffixes = _extension_suffixes()294    if not suffixes:295        # bah, no C_EXTENSION available.  Occurs on pypy without cpyext296        if sys.platform == 'win32':297            suffixes = [".pyd"]298        else:299            suffixes = [".so"]300 301    return suffixes302 303def _ensure_dir(filename):304    dirname = os.path.dirname(filename)305    if dirname and not os.path.isdir(dirname):306        os.makedirs(dirname)307 
codekingpro/portable-devtools · Team Ai