diff --git a/bionetgen/core/utils/utils.py b/bionetgen/core/utils/utils.py index 7d19fd23..604162cc 100644 --- a/bionetgen/core/utils/utils.py +++ b/bionetgen/core/utils/utils.py @@ -1,7 +1,8 @@ -import os, subprocess -from bionetgen.core.exc import BNGPerlError -from distutils import spawn +import os +import shutil +import subprocess +from bionetgen.core.exc import BNGPerlError from bionetgen.core.utils.logging import BNGLogger @@ -589,7 +590,7 @@ def _try_path(candidate_path): return hit # 3) On PATH - bng_on_path = spawn.find_executable("BNG2.pl") + bng_on_path = shutil.which("BNG2.pl") if bng_on_path: tried.append(bng_on_path) hit = _try_path(bng_on_path) @@ -616,7 +617,7 @@ def test_perl(app=None, perl_path=None): logger.debug("Checking if perl is installed.", loc=f"{__file__} : test_perl()") # find path to perl binary if perl_path is None: - perl_path = spawn.find_executable("perl") + perl_path = shutil.which("perl") if perl_path is None: raise BNGPerlError # check if perl is actually working diff --git a/bionetgen/simulator/csimulator.py b/bionetgen/simulator/csimulator.py index 34a6bdcd..4e7dd0d5 100644 --- a/bionetgen/simulator/csimulator.py +++ b/bionetgen/simulator/csimulator.py @@ -1,11 +1,31 @@ import ctypes, os, tempfile, bionetgen import numpy as np -from distutils import ccompiler from .bngsimulator import BNGSimulator from bionetgen.main import BioNetGen from bionetgen.core.exc import BNGCompileError + +def _new_ccompiler(): + """Return a distutils ccompiler instance, sourced from setuptools. + + distutils was removed from the stdlib in Python 3.12; setuptools vendors + the same API as ``setuptools._distutils``. Imported lazily so that + ``import bionetgen`` does not require setuptools at runtime — only + instantiating ``CSimulator`` does. + """ + try: + from setuptools._distutils import ccompiler + except ImportError as exc: + raise BNGCompileError( + None, + "CSimulator requires the distutils ccompiler API, which was " + "removed from the stdlib in Python 3.12. Install setuptools " + "(pip install setuptools) to provide it.", + ) from exc + return ccompiler.new_compiler() + + # This allows access to the CLIs config setup app = BioNetGen() app.setup() @@ -164,7 +184,7 @@ def __init__(self, model_file, generate_network=False): else: print(f"model format not recognized: {model_file}") # set compiler - self.compiler = ccompiler.new_compiler() + self.compiler = _new_ccompiler() self.compiler.add_include_dir(conf.get("cvode_include")) self.compiler.add_library_dir(conf.get("cvode_lib")) # compile shared library