ruptures icon indicating copy to clipboard operation
ruptures copied to clipboard

Issue installing `ruptures` on `aeon` CI

Open MatthewMiddlehurst opened this issue 4 months ago • 13 comments

Yesterday our CI started to fail when installing the package on MacOS (and Python 3.13 for all OS). We use ruptures as an optional dependency, and removing it from the installation list resolves our issue. Not sure if it is just some incompatibility with a recent setuptools/pip version as there has not been many recent changes to the repository.

AttributeError: module 'ruptures' has no attribute '__version__'

Big error log: MacOS Python 3.13.6

   Collecting ruptures>=1.1.9 (from aeon==1.2.0)
    Using cached ruptures-1.1.9.tar.gz (308 kB)
    Installing build dependencies: started
    Installing build dependencies: finished with status 'done'
    Getting requirements to build wheel: started
    Getting requirements to build wheel: finished with status 'error'
    error: subprocess-exited-with-error
    
    × Getting requirements to build wheel did not run successfully.
    │ exit code: 1
    ╰─> [91 lines of output]
        Compiling src/ruptures/detection/_detection/ekcpd.pyx because it changed.
        Compiling src/ruptures/utils/_utils/convert_path_matrix.pyx because it changed.
        [1/2] Cythonizing src/ruptures/detection/_detection/ekcpd.pyx
        [2/2] Cythonizing src/ruptures/utils/_utils/convert_path_matrix.pyx
        /private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/dist.py:759: SetuptoolsDeprecationWarning: License classifiers are deprecated.
        !!
        
                ********************************************************************************
                Please consider removing the following classifiers in favor of a SPDX license expression:
        
                License :: OSI Approved :: BSD License
        
                See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
                ********************************************************************************
        
        !!
          self._finalize_license_expression()
        /private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools_scm/_integration/version_inference.py:51: UserWarning: version of ruptures already set
          warnings.warn(self.message)
        Traceback (most recent call last):
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/expand.py", line 71, in __getattr__
            return next(
                ast.literal_eval(value)
                for target, value in self._find_assignments()
                if isinstance(target, ast.Name) and target.id == attr
            )
        StopIteration
        
        The above exception was the direct cause of the following exception:
        
        Traceback (most recent call last):
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/expand.py", line 185, in read_attr
            value = getattr(StaticModule(module_name, spec), attr_name)
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/expand.py", line 77, in __getattr__
            raise AttributeError(f"{self.name} has no attribute {attr}") from e
        AttributeError: ruptures has no attribute __version__
        
        During handling of the above exception, another exception occurred:
        
        Traceback (most recent call last):
          File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
            main()
            ~~~~^^
          File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 373, in main
            json_out["return_val"] = hook(**hook_input["kwargs"])
                                     ~~~~^^^^^^^^^^^^^^^^^^^^^^^^
          File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 143, in get_requires_for_build_wheel
            return hook(config_settings)
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 331, in get_requires_for_build_wheel
            return self._get_build_requires(config_settings, requirements=[])
                   ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 301, in _get_build_requires
            self.run_setup()
            ~~~~~~~~~~~~~~^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/build_meta.py", line 317, in run_setup
            exec(code, locals())
            ~~~~^^^^^^^^^^^^^^^^
          File "<string>", line 26, in <module>
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/__init__.py", line 115, in setup
            return distutils.core.setup(**attrs)
                   ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/_distutils/core.py", line 160, in setup
            dist.parse_config_files()
            ~~~~~~~~~~~~~~~~~~~~~~~^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/dist.py", line 752, in parse_config_files
            setupcfg.parse_configuration(
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
                self, self.command_options, ignore_option_errors=ignore_option_errors
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            )
            ^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/setupcfg.py", line 188, in parse_configuration
            meta.parse()
            ~~~~~~~~~~^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/setupcfg.py", line 502, in parse
            section_parser_method(section_options)
            ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/setupcfg.py", line 477, in parse_section
            self[name] = value
            ~~~~^^^^^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/setupcfg.py", line 294, in __setitem__
            parsed = self.parsers.get(option_name, lambda x: x)(value)
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/setupcfg.py", line 600, in _parse_version
            return expand.version(self._parse_attr(value, self.package_dir, self.root_dir))
                                  ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/setupcfg.py", line 419, in _parse_attr
            return expand.read_attr(attr_desc, package_dir, root_dir)
                   ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/private/var/folders/y6/nj790rtn62lfktb1sh__79hc0000gn/T/pip-build-env-4igbqe7r/overlay/lib/python3.13/site-packages/setuptools/config/expand.py", line 191, in read_attr
            return getattr(module, attr_name)
        AttributeError: module 'ruptures' has no attribute '__version__'
        [end of output]
    
    note: This error originates from a subprocess, and is likely not a problem with pip.
  error: subprocess-exited-with-error

https://github.com/aeon-toolkit/aeon/actions/runs/17029193884/job/48268880873#step:7:471

MatthewMiddlehurst avatar Aug 18 '25 10:08 MatthewMiddlehurst

Ha weirdly enough, I’ve literally just been fighting with the exact same issue! Was just about to open a ticket myself. After digging in, it looks like the break comes from recent changes in setuptools-scm. My hacky workaround for now is to inject a version.py manually before install, e.g.:

echo 'version = "1.1.9"' src/ruptures/version.py

pip install --no-build-isolation .

Not pretty, but it gets things working until there’s an upstream fix.

tg12 avatar Aug 18 '25 11:08 tg12

We have the same problem on a private gitlab-CI building a docker image with python:3.10-alpine

Zujiry avatar Aug 18 '25 18:08 Zujiry

Same here. Can someone make a wheel for Mac silicon?

likaml avatar Aug 18 '25 20:08 likaml

Its not just Mac, Its to do with Python setup tools, It's cross platform, The same thing is happening to me on a Linux x86 box. This is my full fix in my Dockerfile.

git clone --branch v1.1.9 https://github.com/deepcharles/ruptures.git /tmp/ruptures && \
echo '__version__ = "1.1.9"' >> /tmp/ruptures/src/ruptures/__init__.py && \
pip install /tmp/ruptures

tg12 avatar Aug 18 '25 20:08 tg12

Same here. There is already an issue opened at setuptools_scm in which they suggest not to use:

https://github.com/deepcharles/ruptures/blob/39a837b7e8d3e08d04d33f14749a1a39d86183d2/setup.cfg#L3

PR#353 might be a workaround.

thomasisensee avatar Aug 19 '25 12:08 thomasisensee

Thanks for raising this issue I'll take a look today

deepcharles avatar Aug 19 '25 12:08 deepcharles

We're also seeing this when locally building wheels on MacOS ARM laptops. This error was the reason I left this comment here yesterday, but I didn't realize at the time that this was affecting others: https://github.com/deepcharles/ruptures/pull/340#issuecomment-3198741502

Would be great to avoid wheel building entirely and just use pre-built ones. Thanks!

BryceBeagle avatar Aug 19 '25 15:08 BryceBeagle

Yes!! Would love to see this issue expedited. What was the offending change? @deepcharles

swaritatresolve avatar Aug 20 '25 00:08 swaritatresolve

Hopefully solved in #354

The problem is not super clear to me.

setuptools can't import the package as it installs it, so the line version = attr: ruptures.__version__ in setup.cfg raises an error. This has been observed in https://github.com/pypa/setuptools/issues/1724 There are several workarounds (reordering imports, pointing to original file version.py). The simplest is to simply delete the line. The correct version is still picked up during build.

However, we are in undocumented territory so I'm quite open to suggestions!! Also I'm not sure why this was not breaking before.

Please tell me if that works for you.

I will add support for Python 3.13 now

deepcharles avatar Aug 20 '25 15:08 deepcharles

Your fix removes the issue for me and I can now install without problems from the master branch (MacOS, docker linux/aarch64 and Python 3.13). Thanks!

AartGoossens avatar Aug 21 '25 07:08 AartGoossens

It fixes the problem for us too :) Would appreciate a release 1.1.10!

Zujiry avatar Aug 25 '25 11:08 Zujiry

Same here! would it be possible to release bugfixes for the latest releases?

After pointing to "ruptures @ git+https://github.com/deepcharles/ruptures.git@master" it gets fixed.

msemelman avatar Aug 28 '25 12:08 msemelman

🎉 Finally! New release! Thanks to everyone involved (shout out to @dudustri )

On a side note, I'd like to stray away from the benevolent dictator role and involve more people into ruptures. The community of users would certainly benefit from a broader and more diverse maintainer group.

I'll write a post in Discussion to think about the scope, gouvernance and future of the lib.

Cheers

deepcharles avatar Sep 10 '25 10:09 deepcharles