From efb23b08e74bbfc8573c31a019dd28ea8af9c427 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 15:14:06 -0700 Subject: [PATCH 1/9] pkgs/sage-conf_conda: New, use it in conda install instructions --- pkgs/sage-conf_conda/.gitignore | 6 +++ pkgs/sage-conf_conda/MANIFEST.in | 1 + pkgs/sage-conf_conda/README.rst | 1 + pkgs/sage-conf_conda/VERSION.txt | 1 + pkgs/sage-conf_conda/_sage_conf | 1 + pkgs/sage-conf_conda/bin | 1 + pkgs/sage-conf_conda/pyproject.toml | 1 + pkgs/sage-conf_conda/sage_conf.py | 1 + pkgs/sage-conf_conda/sage_root | 1 + pkgs/sage-conf_conda/setup.cfg | 1 + pkgs/sage-conf_conda/setup.py | 77 +++++++++++++++++++++++++++++ pkgs/sage-conf_pypi/pyproject.toml | 4 +- src/doc/en/installation/conda.rst | 18 ++----- 13 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 pkgs/sage-conf_conda/.gitignore create mode 120000 pkgs/sage-conf_conda/MANIFEST.in create mode 120000 pkgs/sage-conf_conda/README.rst create mode 100644 pkgs/sage-conf_conda/VERSION.txt create mode 120000 pkgs/sage-conf_conda/_sage_conf create mode 120000 pkgs/sage-conf_conda/bin create mode 120000 pkgs/sage-conf_conda/pyproject.toml create mode 120000 pkgs/sage-conf_conda/sage_conf.py create mode 120000 pkgs/sage-conf_conda/sage_root create mode 120000 pkgs/sage-conf_conda/setup.cfg create mode 100644 pkgs/sage-conf_conda/setup.py mode change 100644 => 120000 pkgs/sage-conf_pypi/pyproject.toml diff --git a/pkgs/sage-conf_conda/.gitignore b/pkgs/sage-conf_conda/.gitignore new file mode 100644 index 00000000000..6fdda73c500 --- /dev/null +++ b/pkgs/sage-conf_conda/.gitignore @@ -0,0 +1,6 @@ +/_sage_conf/_conf.py +/build +/dist +/*.egg-info +/.tox +/bin/sage-env-config diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in new file mode 120000 index 00000000000..31ac1aa5100 --- /dev/null +++ b/pkgs/sage-conf_conda/MANIFEST.in @@ -0,0 +1 @@ +../sage-conf_pypi/MANIFEST.in \ No newline at end of file diff --git a/pkgs/sage-conf_conda/README.rst b/pkgs/sage-conf_conda/README.rst new file mode 120000 index 00000000000..feda886cd36 --- /dev/null +++ b/pkgs/sage-conf_conda/README.rst @@ -0,0 +1 @@ +../sage-conf/README.rst \ No newline at end of file diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt new file mode 100644 index 00000000000..7786f0e63e4 --- /dev/null +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -0,0 +1 @@ +10.2.beta5 diff --git a/pkgs/sage-conf_conda/_sage_conf b/pkgs/sage-conf_conda/_sage_conf new file mode 120000 index 00000000000..d92a91bef8c --- /dev/null +++ b/pkgs/sage-conf_conda/_sage_conf @@ -0,0 +1 @@ +../sage-conf/_sage_conf \ No newline at end of file diff --git a/pkgs/sage-conf_conda/bin b/pkgs/sage-conf_conda/bin new file mode 120000 index 00000000000..d7471f37a23 --- /dev/null +++ b/pkgs/sage-conf_conda/bin @@ -0,0 +1 @@ +../sage-conf_pypi/bin \ No newline at end of file diff --git a/pkgs/sage-conf_conda/pyproject.toml b/pkgs/sage-conf_conda/pyproject.toml new file mode 120000 index 00000000000..52c93c824e2 --- /dev/null +++ b/pkgs/sage-conf_conda/pyproject.toml @@ -0,0 +1 @@ +../sage-conf/pyproject.toml \ No newline at end of file diff --git a/pkgs/sage-conf_conda/sage_conf.py b/pkgs/sage-conf_conda/sage_conf.py new file mode 120000 index 00000000000..f4bca8cc55c --- /dev/null +++ b/pkgs/sage-conf_conda/sage_conf.py @@ -0,0 +1 @@ +../sage-conf/sage_conf.py \ No newline at end of file diff --git a/pkgs/sage-conf_conda/sage_root b/pkgs/sage-conf_conda/sage_root new file mode 120000 index 00000000000..2f7df6e4f3f --- /dev/null +++ b/pkgs/sage-conf_conda/sage_root @@ -0,0 +1 @@ +../sage-conf_pypi/sage_root \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.cfg b/pkgs/sage-conf_conda/setup.cfg new file mode 120000 index 00000000000..93df2c80a4b --- /dev/null +++ b/pkgs/sage-conf_conda/setup.cfg @@ -0,0 +1 @@ +../sage-conf/setup.cfg \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py new file mode 100644 index 00000000000..5755edb49ae --- /dev/null +++ b/pkgs/sage-conf_conda/setup.py @@ -0,0 +1,77 @@ +import os +import sys +import shutil +import sysconfig +import platform + +from setuptools import setup +from distutils.command.build_scripts import build_scripts as distutils_build_scripts +from setuptools.command.build_py import build_py as setuptools_build_py +from setuptools.command.egg_info import egg_info as setuptools_egg_info +from distutils.errors import (DistutilsSetupError, DistutilsModuleError, + DistutilsOptionError) + +class build_py(setuptools_build_py): + + def run(self): + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + HERE = os.path.dirname(__file__) + with open(os.path.join(HERE, 'VERSION.txt')) as f: + sage_version = f.read().strip() + # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version + # and architecture. + system = platform.system() + machine = platform.machine() + arch_tag = f'{system}-{machine}' + # TODO: These two should be user-configurable with options passed to "setup.py install" + SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') + SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print(f'Reusing SAGE_ROOT={SAGE_ROOT}') + else: + # config.status and other configure output has to be writable. + # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. + try: + shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists + except Exception: + raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") + cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += """ + --with-python=$CONDA_PREFIX/bin/python \ + --prefix=$CONDA_PREFIX \ + --enable-system-site-packages \ + $(for pkg in $(./sage -package list :standard: \ + --exclude rpy2 \ + --has-file spkg-configure.m4 \ + --has-file distros/conda.txt); do \ + echo --with-system-$pkg=force; \ + done)""" + print(f"Running {cmd}") + sys.stdout.flush() + if os.system(cmd) != 0: + print(f"configure failed; this may be caused by missing build prerequisites.") + sys.stdout.flush() + PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages + os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') + raise DistutilsSetupError("configure failed") + + # In this mode, we never run "make". + + # Install configuration + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + setuptools_build_py.run(self) + +class build_scripts(distutils_build_scripts): + + def run(self): + self.distribution.scripts.append(os.path.join('bin', 'sage-env-config')) + if not self.distribution.entry_points: + self.entry_points = self.distribution.entry_points = dict() + distutils_build_scripts.run(self) + +setup( + cmdclass=dict(build_py=build_py, build_scripts=build_scripts) +) diff --git a/pkgs/sage-conf_pypi/pyproject.toml b/pkgs/sage-conf_pypi/pyproject.toml deleted file mode 100644 index 9787c3bdf00..00000000000 --- a/pkgs/sage-conf_pypi/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" diff --git a/pkgs/sage-conf_pypi/pyproject.toml b/pkgs/sage-conf_pypi/pyproject.toml new file mode 120000 index 00000000000..52c93c824e2 --- /dev/null +++ b/pkgs/sage-conf_pypi/pyproject.toml @@ -0,0 +1 @@ +../sage-conf/pyproject.toml \ No newline at end of file diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 5228611de3b..252c77c39d1 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -135,24 +135,12 @@ Here we assume that you are using a git checkout. By default, the most recent version of Python supported by Sage is installed. You can use the additional option ``python=3.9`` in the above - ``env create`` command to select another Python version (here 3.9). - - - Run the ``configure`` script:: - - $ ./bootstrap - $ ./configure --with-python=$CONDA_PREFIX/bin/python \ - --prefix=$CONDA_PREFIX \ - $(for pkg in $(./sage -package list :standard: \ - --exclude rpy2 \ - --has-file spkg-configure.m4 \ - --has-file distros/conda.txt); do \ - echo --with-system-$pkg=force; \ - done) + ``env create`` command to select another Python version (here 3.9). - Install the build prerequisites and the Sage library:: - $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf ./pkgs/sage-setup - $ pip install --no-build-isolation -v -v --editable ./src + $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf_conda ./pkgs/sage-setup + $ pip install --no-build-isolation --config-settings editable_mode=compat -v -v --editable ./src - Verify that Sage has been installed:: From ab0960722972c43d097671f806ec567e9fd31df2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 27 Sep 2023 17:23:56 -0700 Subject: [PATCH 2/9] src/doc/en/installation/conda.rst: Add note on editable_mode=compat --- src/doc/en/installation/conda.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 252c77c39d1..063a9fb06cf 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -171,3 +171,11 @@ To build the documentation, use:: $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-docbuild $ sage --docbuild all html + +.. NOTE:: + + The switch ``--config-settings editable_mode=compat`` restores the + `legacy setuptools implementation of editable installations + `_. + Adventurous developers may omit this switch to try the modern, + PEP-660 implementation of editable installations, see :issue:`34209`. From 944bc9723abf50d86036342e24ebd29306f2b9e8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 15:53:55 -0700 Subject: [PATCH 3/9] pkgs/sage-conf_conda: Fix setup.py --- pkgs/sage-conf_conda/setup.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 5755edb49ae..e2c8d857b9a 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -3,6 +3,9 @@ import shutil import sysconfig import platform +import fnmatch + +from pathlib import Path from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts @@ -25,27 +28,28 @@ def run(self): arch_tag = f'{system}-{machine}' # TODO: These two should be user-configurable with options passed to "setup.py install" SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') - SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + + def ignore(path, names): + # exclude all embedded src trees + if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + return ['src'] + ### ignore more stuff --- .tox etc. + return [name for name in names + if name in ('.tox',)] + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): print(f'Reusing SAGE_ROOT={SAGE_ROOT}') else: # config.status and other configure output has to be writable. # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. try: - shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists - except Exception: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") - cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" - cmd += """ - --with-python=$CONDA_PREFIX/bin/python \ - --prefix=$CONDA_PREFIX \ - --enable-system-site-packages \ - $(for pkg in $(./sage -package list :standard: \ - --exclude rpy2 \ - --has-file spkg-configure.m4 \ - --has-file distros/conda.txt); do \ - echo --with-system-$pkg=force; \ - done)""" + shutil.copytree('sage_root', SAGE_ROOT, + ignore=ignore) # will fail if already exists + except Exception as e: + raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again. (Exception: {e})") + cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' + cmd += ' $(for pkg in $(build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' print(f"Running {cmd}") sys.stdout.flush() if os.system(cmd) != 0: From 870ce5d32b19946e21bdf26f455dd1a962cba7aa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 12:16:08 -0700 Subject: [PATCH 4/9] pkgs/sage-conf_conda/setup.py: In editable mode, do not make a copy of SAGE_ROOT --- pkgs/sage-conf_conda/setup.py | 75 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index e2c8d857b9a..4a8aaef9f83 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -10,15 +10,51 @@ from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py -from setuptools.command.egg_info import egg_info as setuptools_egg_info -from distutils.errors import (DistutilsSetupError, DistutilsModuleError, - DistutilsOptionError) +from setuptools.errors import SetupError + class build_py(setuptools_build_py): def run(self): - DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + HERE = os.path.dirname(__file__) + if self.editable_mode: + SAGE_ROOT = os.path.join(HERE, 'sage_root') + else: + SAGE_ROOT = self._create_writable_sage_root() + + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') + else: + cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' + cmd += ' $(for pkg in $(PATH="build/bin:$PATH" build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' + print(f"Running {cmd}") + sys.stdout.flush() + if os.system(cmd) != 0: + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print("Warning: A configuration has been written, but the configure script has exited with an error. " + "Carefully check any error messages before continuing.") + else: + print(f"Error: The configure script has failed; this may be caused by missing build prerequisites.") + sys.stdout.flush() + PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages + os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') + raise SetupError("configure failed") + + # In this mode, we never run "make". + + if not self.editable_mode: + # Install configuration + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + + setuptools_build_py.run(self) + + def _create_writable_sage_root(self): + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) with open(os.path.join(HERE, 'VERSION.txt')) as f: sage_version = f.read().strip() # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version @@ -26,7 +62,7 @@ def run(self): system = platform.system() machine = platform.machine() arch_tag = f'{system}-{machine}' - # TODO: These two should be user-configurable with options passed to "setup.py install" + # TODO: Should be user-configurable with config settings SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') def ignore(path, names): @@ -35,38 +71,20 @@ def ignore(path, names): return ['src'] ### ignore more stuff --- .tox etc. return [name for name in names - if name in ('.tox',)] + if name in ('.tox', '.git', '__pycache__')] - if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): - print(f'Reusing SAGE_ROOT={SAGE_ROOT}') - else: + if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): # config.status and other configure output has to be writable. # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. try: shutil.copytree('sage_root', SAGE_ROOT, ignore=ignore) # will fail if already exists except Exception as e: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again. (Exception: {e})") - cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" - cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' - cmd += ' $(for pkg in $(build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' - print(f"Running {cmd}") - sys.stdout.flush() - if os.system(cmd) != 0: - print(f"configure failed; this may be caused by missing build prerequisites.") - sys.stdout.flush() - PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages - os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') - raise DistutilsSetupError("configure failed") + raise SetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured ({e}). " + "Please either remove it and try again, or install in editable mode (pip install -e).") - # In this mode, we never run "make". + return SAGE_ROOT - # Install configuration - shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), - os.path.join(HERE, '_sage_conf', '_conf.py')) - shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), - os.path.join(HERE, 'bin', 'sage-env-config')) - setuptools_build_py.run(self) class build_scripts(distutils_build_scripts): @@ -76,6 +94,7 @@ def run(self): self.entry_points = self.distribution.entry_points = dict() distutils_build_scripts.run(self) + setup( cmdclass=dict(build_py=build_py, build_scripts=build_scripts) ) From 77925d09a8116bfbce4c3c29a529b408f4df560b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 14:38:22 -0700 Subject: [PATCH 5/9] pkgs/sage-conf_conda: Make sage_root a symlink to SAGE_ROOT --- pkgs/sage-conf_conda/MANIFEST.in | 54 +++++++++++++++++++++++++++++++- pkgs/sage-conf_conda/sage_root | 2 +- pkgs/sage-conf_conda/setup.py | 8 +++-- 3 files changed, 60 insertions(+), 4 deletions(-) mode change 120000 => 100644 pkgs/sage-conf_conda/MANIFEST.in diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in deleted file mode 120000 index 31ac1aa5100..00000000000 --- a/pkgs/sage-conf_conda/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -../sage-conf_pypi/MANIFEST.in \ No newline at end of file diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in new file mode 100644 index 00000000000..ea5f85f8c99 --- /dev/null +++ b/pkgs/sage-conf_conda/MANIFEST.in @@ -0,0 +1,53 @@ +prune .tox +include VERSION.txt +graft bin +exclude bin/sage-env-config # generated by configure + +prune sage_root +include sage_root/Makefile +include sage_root/README.md +include sage_root/VERSION.txt +include sage_root/bootstrap +include sage_root/bootstrap-conda +graft sage_root/build +prune sage_root/build/.tox +exclude sage_root/build/bin/sage-build-env-config # generated by configure +exclude sage_root/build/make/Makefile-auto # generated by configure +exclude sage_root/build/make/Makefile # generated by configure + +# These sources are not needed because individual distributions of these are made. +prune sage_root/build/pkgs/*/src* + +graft sage_root/config +include sage_root/configure +include sage_root/configure.ac +graft sage_root/m4 + +# Only these pkgs are needed (because of dependencies on source files, +# see "git grep SAGE_ROOT build/pkgs/*/dependencies") +graft sage_root/pkgs/sage-conf +prune sage_root/pkgs/sage-conf/build +prune sage_root/pkgs/sage-conf/dist +prune sage_root/pkgs/sage-conf/*.egg-info +exclude sage_root/pkgs/sage-conf/_sage_conf/_conf.py # generated by configure +graft sage_root/pkgs/sage-docbuild +prune sage_root/pkgs/sage-docbuild/build +prune sage_root/pkgs/sage-docbuild/dist +prune sage_root/pkgs/sage-docbuild/*.egg-info + +graft sage_root/src/_sage_conf +include sage_root/src/bin/sage-env +include sage_root/src/bin/sage-env-config.in +include sage_root/src/bin/sage-src-env-config.in +include sage_root/src/bin/sage-venv-config +include sage_root/src/bin/sage-version.sh +include sage_root/src/doc/bootstrap # FIXME: should move to builds/pkgs/sagemath_doc_html/ + +global-exclude .tox +global-exclude *~* +global-exclude *.bak +global-exclude *.orig +global-exclude __pycache__ +global-exclude *.py[co] +global-exclude *.so +global-exclude .DS_Store diff --git a/pkgs/sage-conf_conda/sage_root b/pkgs/sage-conf_conda/sage_root index 2f7df6e4f3f..c25bddb6dd4 120000 --- a/pkgs/sage-conf_conda/sage_root +++ b/pkgs/sage-conf_conda/sage_root @@ -1 +1 @@ -../sage-conf_pypi/sage_root \ No newline at end of file +../.. \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 4a8aaef9f83..8d5d9b303fe 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -44,8 +44,11 @@ def run(self): # In this mode, we never run "make". - if not self.editable_mode: - # Install configuration + # Copy over files generated by the configure script + # (see configure.ac AC_CONFIG_FILES) + if self.editable_mode: + pass # same file + else: shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), os.path.join(HERE, '_sage_conf', '_conf.py')) shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), @@ -54,6 +57,7 @@ def run(self): setuptools_build_py.run(self) def _create_writable_sage_root(self): + HERE = os.path.dirname(__file__) DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) with open(os.path.join(HERE, 'VERSION.txt')) as f: sage_version = f.read().strip() From 66a407eaa4ced5af6155eb98ca379bd3770b3c7e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 15:08:05 -0700 Subject: [PATCH 6/9] Update README and messages --- pkgs/sage-conf/README.rst | 12 +++++++++++- pkgs/sage-conf_conda/setup.py | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pkgs/sage-conf/README.rst b/pkgs/sage-conf/README.rst index c968612aef2..5730592e35a 100644 --- a/pkgs/sage-conf/README.rst +++ b/pkgs/sage-conf/README.rst @@ -78,10 +78,20 @@ sage_conf in the SageMath distribution The original version of the distribution package ``sage_conf`` is used internally in the SageMath distribution. It is provided in the directory `pkgs/sage-conf `_. -This version of the package is generated by the Sage distribution's ``configure`` +This version of the package is generated by the Sage distribution's ``./configure`` script. +sage_conf for conda +------------------- + +The version of the distribution package in the directory +`pkgs/sage-conf_conda `_ +is used in an experimental installation method of SageMath, where all packages +are provided by conda. This method is described in +https://doc.sagemath.org/html/en/installation/conda.html#using-conda-to-provide-all-dependencies-for-the-sage-library-experimental + + sage_conf in downstream distributions ------------------------------------- diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 8d5d9b303fe..af0177f8ea4 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -34,12 +34,12 @@ def run(self): if os.system(cmd) != 0: if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): print("Warning: A configuration has been written, but the configure script has exited with an error. " - "Carefully check any error messages before continuing.") + "Carefully check any messages above before continuing.") else: print(f"Error: The configure script has failed; this may be caused by missing build prerequisites.") sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages - os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') + os.system(f'cd {SAGE_ROOT} && export PACKAGES="$(build/bin/sage-get-system-packages conda {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command conda --verbose --sudo install $PACKAGES && echo ""') raise SetupError("configure failed") # In this mode, we never run "make". From 18aebf4077a8d7a98f688ee0548e8ce978a561a0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 20:13:50 -0700 Subject: [PATCH 7/9] pkgs/sage-conf_conda/setup.py: Skip some files generated in editable mode when copying in non-editable mode --- pkgs/sage-conf_conda/setup.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index af0177f8ea4..a2333f6b8d5 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -10,6 +10,7 @@ from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py +from setuptools.command.editable_wheel import editable_wheel as setuptools_editable_wheel from setuptools.errors import SetupError @@ -75,7 +76,9 @@ def ignore(path, names): return ['src'] ### ignore more stuff --- .tox etc. return [name for name in names - if name in ('.tox', '.git', '__pycache__')] + if name in ('.tox', '.git', '__pycache__', + 'prefix', 'local', 'venv', 'upstream', + 'config.status', 'config.log', 'logs')] if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): # config.status and other configure output has to be writable. @@ -99,6 +102,16 @@ def run(self): distutils_build_scripts.run(self) +class editable_wheel(setuptools_editable_wheel): + r""" + Customized so that exceptions raised by our build_py + do not lead to the "Customization incompatible with editable install" message + """ + _safely_run = setuptools_editable_wheel.run_command + + setup( - cmdclass=dict(build_py=build_py, build_scripts=build_scripts) + cmdclass=dict(build_py=build_py, + build_scripts=build_scripts, + editable_wheel=editable_wheel) ) From 2c54bdc06263c74078fda88eb5fec37be055ca97 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 20:15:00 -0700 Subject: [PATCH 8/9] pkgs/sage-conf_pypi/setup.py: Restructure like ..._conda, prepare for editable mode --- .gitignore | 10 ++++ pkgs/sage-conf_pypi/setup.py | 104 +++++++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index efdbfa8f616..2cec8a0cf62 100644 --- a/.gitignore +++ b/.gitignore @@ -175,6 +175,16 @@ build/bin/sage-build-env-config /pkgs/*/*.egg-info /pkgs/*/.tox +/pkgs/sage-conf_pypi/sage_root/config.log +/pkgs/sage-conf_pypi/sage_root/config.status +/pkgs/sage-conf_pypi/sage_root/local/ +/pkgs/sage-conf_pypi/sage_root/logs/ +/pkgs/sage-conf_pypi/sage_root/prefix +/pkgs/sage-conf_pypi/sage_root/src/bin/sage-env-config +/pkgs/sage-conf_pypi/sage_root/src/bin/sage-src-env-config +/pkgs/sage-conf_pypi/sage_root/upstream/ +/pkgs/sage-conf_pypi/sage_root/venv + /pkgs/sagemath-objects/setup.cfg /pkgs/sagemath-bliss/setup.cfg /pkgs/sagemath-coxeter3/setup.cfg diff --git a/pkgs/sage-conf_pypi/setup.py b/pkgs/sage-conf_pypi/setup.py index a689f4d617b..16686a848c9 100644 --- a/pkgs/sage-conf_pypi/setup.py +++ b/pkgs/sage-conf_pypi/setup.py @@ -3,40 +3,35 @@ import shutil import sysconfig import platform +import fnmatch from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py -from setuptools.command.egg_info import egg_info as setuptools_egg_info -from distutils.errors import (DistutilsSetupError, DistutilsModuleError, - DistutilsOptionError) +from setuptools.command.editable_wheel import editable_wheel as setuptools_editable_wheel +from setuptools.errors import SetupError + class build_py(setuptools_build_py): def run(self): - DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) HERE = os.path.dirname(__file__) - with open(os.path.join(HERE, 'VERSION.txt')) as f: - sage_version = f.read().strip() + if self.editable_mode: + SAGE_ROOT = os.path.join(HERE, 'sage_root') + else: + SAGE_ROOT = self._create_writable_sage_root() + # For convenience, set up the homebrew env automatically. This is a no-op if homebrew is not present. - SETENV = '(. ./.homebrew-build-env 2> /dev/null || :)' - # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version - # and architecture. - system = platform.system() - machine = platform.machine() - arch_tag = f'{system}-{machine}' - # TODO: These two should be user-configurable with options passed to "setup.py install" - SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}') + if os.environ.get('CONDA_PREFIX', ''): + SETENV = ':' + else: + SETENV = '(. ./.homebrew-build-env 2> /dev/null || :)' + SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): - print(f'Reusing SAGE_ROOT={SAGE_ROOT}') + print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') else: - # config.status and other configure output has to be writable. - # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. - try: - shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists - except Exception: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" print(f"Running {cmd}") sys.stdout.flush() @@ -45,7 +40,18 @@ def run(self): sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') - raise DistutilsSetupError("configure failed") + raise SetupError("configure failed") + + # Copy over files generated by the configure script + # (see configure.ac AC_CONFIG_FILES) + if self.editable_mode: + pass # same file + else: + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + # Here we run "make build" -- which builds everything except for sagelib because we # used configure --disable-sagelib # Alternative: @@ -61,13 +67,44 @@ def run(self): if os.system(cmd) != 0: raise DistutilsSetupError(f"make {TARGETS} failed") - # Install configuration - shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), - os.path.join(HERE, '_sage_conf', '_conf.py')) - shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), - os.path.join(HERE, 'bin', 'sage-env-config')) setuptools_build_py.run(self) + def _create_writable_sage_root(self): + HERE = os.path.dirname(__file__) + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + with open(os.path.join(HERE, 'VERSION.txt')) as f: + sage_version = f.read().strip() + # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version + # and architecture. + system = platform.system() + machine = platform.machine() + arch_tag = f'{system}-{machine}' + # TODO: Should be user-configurable with config settings + SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}') + + def ignore(path, names): + # exclude all embedded src trees + if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + return ['src'] + ### ignore more stuff --- .tox etc. + return [name for name in names + if name in ('.tox', '.git', '__pycache__', + 'prefix', 'local', 'venv', 'upstream', + 'config.status', 'config.log', 'logs')] + + if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + # config.status and other configure output has to be writable. + # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. + try: + shutil.copytree('sage_root', SAGE_ROOT, + ignore=ignore) # will fail if already exists + except Exception as e: + raise SetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured ({e}). " + "Please either remove it and try again, or install in editable mode (pip install -e).") + + return SAGE_ROOT + + class build_scripts(distutils_build_scripts): def run(self): @@ -76,6 +113,17 @@ def run(self): self.entry_points = self.distribution.entry_points = dict() distutils_build_scripts.run(self) + +class editable_wheel(setuptools_editable_wheel): + r""" + Customized so that exceptions raised by our build_py + do not lead to the "Customization incompatible with editable install" message + """ + _safely_run = setuptools_editable_wheel.run_command + + setup( - cmdclass=dict(build_py=build_py, build_scripts=build_scripts) + cmdclass=dict(build_py=build_py, + build_scripts=build_scripts, + editable_wheel=editable_wheel) ) From 46c28c0d104535f685931659e864efcd7be7e09b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 20:28:31 -0700 Subject: [PATCH 9/9] pkgs/sage-conf_conda/setup.py: Exit early when no conda env is active --- pkgs/sage-conf_conda/setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index a2333f6b8d5..21977a81ca4 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -24,6 +24,10 @@ def run(self): else: SAGE_ROOT = self._create_writable_sage_root() + if not os.environ.get('CONDA_PREFIX', ''): + raise SetupError('No conda environment is active. ' + 'See https://doc.sagemath.org/html/en/installation/conda.html on how to get started.') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') else: