Skip to content

Commit

Permalink
Merge branch 'sage_conf_conda' into conda_legacy_editable
Browse files Browse the repository at this point in the history
  • Loading branch information
mkoeppe committed Oct 5, 2023
2 parents d1922c2 + 46c28c0 commit 8976db2
Show file tree
Hide file tree
Showing 16 changed files with 296 additions and 46 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion pkgs/sage-conf/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/sagemath/sage/tree/develop/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 <https://github.com/sagemath/sage/tree/develop/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
-------------------------------------

Expand Down
6 changes: 6 additions & 0 deletions pkgs/sage-conf_conda/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/_sage_conf/_conf.py
/build
/dist
/*.egg-info
/.tox
/bin/sage-env-config
53 changes: 53 additions & 0 deletions pkgs/sage-conf_conda/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/README.rst
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/VERSION.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10.2.beta5
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/_sage_conf
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/bin
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/pyproject.toml
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/sage_conf.py
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/sage_root
1 change: 1 addition & 0 deletions pkgs/sage-conf_conda/setup.cfg
121 changes: 121 additions & 0 deletions pkgs/sage-conf_conda/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import os
import sys
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
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


class build_py(setuptools_build_py):

def run(self):

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 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:
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 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 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".

# 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'))

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}-conda')

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):
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)


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,
editable_wheel=editable_wheel)
)
3 changes: 0 additions & 3 deletions pkgs/sage-conf_pypi/pyproject.toml

This file was deleted.

1 change: 1 addition & 0 deletions pkgs/sage-conf_pypi/pyproject.toml
104 changes: 76 additions & 28 deletions pkgs/sage-conf_pypi/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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:
Expand All @@ -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):
Expand All @@ -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)
)
Loading

0 comments on commit 8976db2

Please sign in to comment.