Skip to content

openscm_runner.adapters cannot be imported on Python 3.12+ without setuptools (distutils removed) #110

Description

@karla-spiller

Summary

import openscm_runner.adapters fails on Python 3.12 and later unless setuptools happens to be installed, because the CICERO-SCM adapter imports distutils, which was removed from the standard library in 3.12 (PEP 632).

Cause

adapters/__init__.py eagerly imports every adapter:

from .ciceroscm_adapter import CICEROSCM

and adapters/ciceroscm_adapter/ciceroscm_wrapper.py:10 does:

from distutils import dir_util

So importing the package at all pulls in distutils, regardless of which climate model the caller intends to use. On 3.12+ that only resolves through the _distutils_hack shim that setuptools installs.

Reproducing

Verified against v0.13.0 (current release) on Python 3.13:

>>> import openscm_runner.adapters
ModuleNotFoundError: No module named 'distutils'
  File ".../openscm_runner/adapters/__init__.py", line 6, in <module>
    from .ciceroscm_adapter import CICEROSCM
  File ".../ciceroscm_adapter/ciceroscm_wrapper.py", line 10, in <module>
    from distutils import dir_util

Why this bites in practice

setuptools is present in most environments by accident rather than by declaration, so the failure is environment-dependent and surfaces late. Tools such as uv do not install it into a project environment at all, so the same lockfile works on one machine and not another. In our case it made a downstream pipeline unable to run its climate stage on one checkout while an otherwise identical one worked, with nothing in either lockfile to explain the difference.

Possible fixes

  • dir_util.copy_tree is the only usage as far as I can see, and shutil.copytree(..., dirs_exist_ok=True) covers it on all supported versions. shutil is already imported in that module.
  • Alternatively, import the adapters lazily in adapters/__init__.py, so a distutils dependency in one adapter does not break users of the others.

Happy to open a PR for either if you have a preference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions