Ticket #13887: 13887_fortran_tmp_dir.patch

File 13887_fortran_tmp_dir.patch, 4.9 KB (added by jdemeyer, 8 years ago)
  • sage/misc/inline_fortran.py

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1356860777 -3600
    # Node ID 6330cd9fe67b6d236f5756db60734eacbaa2d3f1
    # Parent  65b59ae52ccbd75c5f61f2dab1c6634cfc3ea722
    In inline_fortran, use a temporary directory instead of the current directory
    
    diff --git a/sage/misc/inline_fortran.py b/sage/misc/inline_fortran.py
    a b  
     1"""
     2Fortran compiler
     3"""
    14import __builtin__
    25import os
    36
    4 from sage.misc.temporary_file import tmp_filename
    5 
    6 count=0
     7from sage.misc.temporary_file import tmp_dir
    78
    89
    910class InlineFortran:
     
    3435
    3536        TESTS::
    3637
     38            sage: os.chdir(SAGE_ROOT)
    3739            sage: fortran.eval("SYNTAX ERROR !@#$")
    3840            Traceback (most recent call last):
    3941            ...
    4042            RuntimeError: failed to compile Fortran code:...
     43            sage: os.getcwd() == SAGE_ROOT
     44            True
    4145        """
    4246        if len(x.splitlines()) == 1 and os.path.exists(x):
    4347            filename = x
    4448            x = open(x).read()
    4549            if filename.lower().endswith('.f90'):
    4650                x = '!f90\n' + x
    47         global count
    4851
    4952        from numpy import f2py
    50         old_import_path=os.sys.path
    51         cwd=os.getcwd()
    52         os.sys.path.append(cwd)
    5353
    54         #name = tmp_dir() + '/fortran_module_%d'%count
    55         name = 'fortran_module_%d'%count
    56         if os.path.exists(name):
    57             os.unlink(name)
    58         s_lib_path=""
    59         s_lib=""
    60         for s in self.library_paths:
    61             s_lib_path=s_lib_path+"-L"+s+" "
     54        # Create everything in a temporary directory
     55        mytmpdir = tmp_dir()
    6256
    63         for s in self.libraries:
    64             s_lib=s_lib +"-l"+s + " "
     57        try:
     58            old_cwd = os.getcwd()
     59            os.chdir(mytmpdir)
    6560
    66         # if the first line has !f90 as a comment gfortran will treat it as
    67         # fortran 90 code
    68         if x.startswith('!f90'):
    69             fname = tmp_filename(ext='.f90')
    70         else:
    71             fname = tmp_filename(ext='.f')
    72 
    73         log = tmp_filename()
    74         extra_args = '--quiet --f77exec=sage-inline-fortran --f90exec=sage-inline-fortran %s %s >"%s" 2>&1'%(
    75             s_lib_path, s_lib, log)
    76 
    77         f2py.compile(x, name, extra_args = extra_args, source_fn=fname)
    78 
    79         log_string = open(log).read()
    80 
    81         os.unlink(log)
    82         os.unlink(fname)
    83 
    84         # f2py.compile() doesn't raise any exception if it fails.
    85         # So we manually check whether the compiled file exists.
    86         # NOTE: the .so extension is used, even on OS X where .dylib
    87         # would be expected.
    88         soname = name + '.so'
    89         if not os.path.isfile(soname):
    90             raise RuntimeError("failed to compile Fortran code:\n" + log_string)
    91 
    92         if self.verbose:
    93             print log_string
    94        
    95         count += 1
    96         try:
    97             m=__builtin__.__import__(name)
    98         except ImportError:
    99             if not self.verbose:
     61            old_import_path = os.sys.path
     62            os.sys.path.append(mytmpdir)
     63   
     64            name = "fortran_module"  # Python module name
     65            # if the first line has !f90 as a comment, gfortran will
     66            # treat it as Fortran 90 code
     67            if x.startswith('!f90'):
     68                fortran_file = name + '.f90'
     69            else:
     70                fortran_file = name + '.f'
     71   
     72            s_lib_path = ""
     73            s_lib = ""
     74            for s in self.library_paths:
     75                s_lib_path = s_lib_path + "-L%s "
     76   
     77            for s in self.libraries:
     78                s_lib = s_lib + "-l%s "%s
     79   
     80            log = name + ".log"
     81            extra_args = '--quiet --f77exec=sage-inline-fortran --f90exec=sage-inline-fortran %s %s >"%s" 2>&1'%(
     82                s_lib_path, s_lib, log)
     83   
     84            f2py.compile(x, name, extra_args = extra_args, source_fn=fortran_file)
     85            log_string = open(log).read()
     86   
     87            # f2py.compile() doesn't raise any exception if it fails.
     88            # So we manually check whether the compiled file exists.
     89            # NOTE: the .so extension is used, even on OS X where .dylib
     90            # might be expected.
     91            soname = name + '.so'
     92            if not os.path.isfile(soname):
     93                raise RuntimeError("failed to compile Fortran code:\n" + log_string)
     94   
     95            if self.verbose:
    10096                print log_string
    101             return
     97           
     98            m = __builtin__.__import__(name)
    10299        finally:
    103             os.sys.path=old_import_path
    104             os.unlink(soname)
     100            os.sys.path = old_import_path
     101            os.chdir(old_cwd)
     102            try:
     103                import shutil
     104                shutil.rmtree(mytmpdir)
     105            except OSError:
     106                # This can fail for example over NFS
     107                pass
    105108       
    106109        for k, x in m.__dict__.iteritems():
    107110            if k[0] != '_':