Compile and import a f2py module, built from the given files.
(source_files, options=[], skip=[], only=[], module_name=None)
| 100 | |
| 101 | @_memoize |
| 102 | def build_module(source_files, options=[], skip=[], only=[], module_name=None): |
| 103 | """ |
| 104 | Compile and import a f2py module, built from the given files. |
| 105 | |
| 106 | """ |
| 107 | |
| 108 | code = f"import sys; sys.path = {sys.path!r}; import numpy.f2py; numpy.f2py.main()" |
| 109 | |
| 110 | d = get_module_dir() |
| 111 | |
| 112 | # Copy files |
| 113 | dst_sources = [] |
| 114 | f2py_sources = [] |
| 115 | for fn in source_files: |
| 116 | if not os.path.isfile(fn): |
| 117 | raise RuntimeError("%s is not a file" % fn) |
| 118 | dst = os.path.join(d, os.path.basename(fn)) |
| 119 | shutil.copyfile(fn, dst) |
| 120 | dst_sources.append(dst) |
| 121 | |
| 122 | base, ext = os.path.splitext(dst) |
| 123 | if ext in (".f90", ".f", ".c", ".pyf"): |
| 124 | f2py_sources.append(dst) |
| 125 | |
| 126 | assert f2py_sources |
| 127 | |
| 128 | # Prepare options |
| 129 | if module_name is None: |
| 130 | module_name = get_temp_module_name() |
| 131 | f2py_opts = ["-c", "-m", module_name] + options + f2py_sources |
| 132 | if skip: |
| 133 | f2py_opts += ["skip:"] + skip |
| 134 | if only: |
| 135 | f2py_opts += ["only:"] + only |
| 136 | |
| 137 | # Build |
| 138 | cwd = os.getcwd() |
| 139 | try: |
| 140 | os.chdir(d) |
| 141 | cmd = [sys.executable, "-c", code] + f2py_opts |
| 142 | p = subprocess.Popen(cmd, |
| 143 | stdout=subprocess.PIPE, |
| 144 | stderr=subprocess.STDOUT) |
| 145 | out, err = p.communicate() |
| 146 | if p.returncode != 0: |
| 147 | raise RuntimeError("Running f2py failed: %s\n%s" % |
| 148 | (cmd[4:], asunicode(out))) |
| 149 | finally: |
| 150 | os.chdir(cwd) |
| 151 | |
| 152 | # Partial cleanup |
| 153 | for fn in dst_sources: |
| 154 | os.unlink(fn) |
| 155 | |
| 156 | # Rebase (Cygwin-only) |
| 157 | if sys.platform == "cygwin": |
| 158 | # If someone starts deleting modules after import, this will |
| 159 | # need to change to record how big each module is, rather than |
no test coverage detected