Skip to content

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

Open

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.

Activity

  1. maritsandstad commented on Aug 6, 2026

    @maritsandstad
    Collaborator

    Thanks @karla-spiller ! I'll have a look at that now, see if I can possibly fix with either one of your suggestions, or seeing if we can do without distutils entirely...

  2. maritsandstad commented on Aug 6, 2026

    @maritsandstad
    Collaborator

    @karla-spiller : Actually we've solved this with various updates included in PR #97 , once that comes in it should be solved. Maybe we can go back and do a rereview of that @znicholls ? I'll, go over and close all the outdated comments and reping you for a new review over there.

  3. karla-spiller commented on Aug 6, 2026

    @karla-spiller
    Author

    Thanks @maritsandstad! Glad to hear it has already been solved. Sorry, I didn't actually mean to bother you with this - this was Claude getting a bit over enthusiastic.

  4. maritsandstad commented on Aug 6, 2026

    @maritsandstad
    Collaborator

    No worries @karla-spiller, well defined issues are always welcome, in fact, interest at all here is kind of once in a blue moon, and always nice to see :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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