Issue installing `ruptures` on `aeon` CI
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
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.
We have the same problem on a private gitlab-CI building a docker image with python:3.10-alpine
Same here. Can someone make a wheel for Mac silicon?
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
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.
Thanks for raising this issue I'll take a look today
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!
Yes!! Would love to see this issue expedited. What was the offending change? @deepcharles
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
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!
It fixes the problem for us too :) Would appreciate a release 1.1.10!
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.
🎉 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