diff --git a/build/pkgs/sagelib/spkg-install.in b/build/pkgs/sagelib/spkg-install.in index 8b3b4485504..0b1329bf1b1 100644 --- a/build/pkgs/sagelib/spkg-install.in +++ b/build/pkgs/sagelib/spkg-install.in @@ -60,20 +60,16 @@ if [ "$SAGE_EDITABLE" = yes ]; then cd $SAGE_PKGS/sagelib/src && time sdh_setup_bdist_wheel && sdh_store_wheel . fi else + # Now implied: "$SAGE_WHEELS" = yes # Make sure that an installed old version of sagelib in which sage is an ordinary package # does not shadow the namespace package sage during the build. (cd "$SITEPACKAGESDIR" && rm -f sage/__init__.py) # Likewise, we should remove the egg-link that may have been installed previously. (cd "$SITEPACKAGESDIR" && rm -f sagemath-standard.egg-link) - if [ "$SAGE_WHEELS" = yes ]; then - # Use --no-build-isolation to avoid rebuilds because of dependencies: - # Compiling sage/interfaces/sagespawn.pyx because it depends on /private/var/folders/38/wnh4gf1552g_crsjnv2vmmww0000gp/T/pip-build-env-609n5985/overlay/lib/python3.10/site-packages/Cython/Includes/posix/unistd.pxd - sdh_pip_install --no-build-isolation . - else - SAGE_OPTIONAL_PACKAGES_WITH_EXTENSIONS+="mcqd,tdlib,coxeter3,sirocco,meataxe,bliss" - python3 -u setup.py --no-user-cfg build install || exit 1 - fi + # Use --no-build-isolation to avoid rebuilds because of dependencies: + # Compiling sage/interfaces/sagespawn.pyx because it depends on /private/var/folders/38/wnh4gf1552g_crsjnv2vmmww0000gp/T/pip-build-env-609n5985/overlay/lib/python3.10/site-packages/Cython/Includes/posix/unistd.pxd + sdh_pip_install --no-build-isolation . fi # Remove (potentially invalid) star import caches. diff --git a/build/pkgs/sagemath_bliss/spkg-install.in b/build/pkgs/sagemath_bliss/spkg-install.in index ccd53947ab0..2a2d7efba78 100644 --- a/build/pkgs/sagemath_bliss/spkg-install.in +++ b/build/pkgs/sagemath_bliss/spkg-install.in @@ -10,9 +10,6 @@ if [ "$SAGE_EDITABLE" = yes ]; then sdh_setup_bdist_wheel && sdh_store_wheel . fi else - if [ "$SAGE_WHEELS" = yes ]; then - # Modularized install via wheels - sdh_pip_install . - # else nothing to do in legacy direct installation. - fi + # Modularized install via wheels. Now implied: "$SAGE_WHEELS" = yes + sdh_pip_install . fi diff --git a/build/pkgs/sagemath_coxeter3/spkg-install.in b/build/pkgs/sagemath_coxeter3/spkg-install.in deleted file mode 100644 index ccd53947ab0..00000000000 --- a/build/pkgs/sagemath_coxeter3/spkg-install.in +++ /dev/null @@ -1,18 +0,0 @@ -cd src - -export PIP_NO_INDEX=true -export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" - -if [ "$SAGE_EDITABLE" = yes ]; then - # SAGE_ROOT/src/setup.py installs everything, nothing to do... - if [ "$SAGE_WHEELS" = yes ]; then - # ... except we build the wheel if requested - sdh_setup_bdist_wheel && sdh_store_wheel . - fi -else - if [ "$SAGE_WHEELS" = yes ]; then - # Modularized install via wheels - sdh_pip_install . - # else nothing to do in legacy direct installation. - fi -fi diff --git a/build/pkgs/sagemath_coxeter3/spkg-install.in b/build/pkgs/sagemath_coxeter3/spkg-install.in new file mode 120000 index 00000000000..e38ca3ace8b --- /dev/null +++ b/build/pkgs/sagemath_coxeter3/spkg-install.in @@ -0,0 +1 @@ +../sagemath_bliss/spkg-install.in \ No newline at end of file diff --git a/build/pkgs/sagemath_mcqd/spkg-install.in b/build/pkgs/sagemath_mcqd/spkg-install.in deleted file mode 100644 index ccd53947ab0..00000000000 --- a/build/pkgs/sagemath_mcqd/spkg-install.in +++ /dev/null @@ -1,18 +0,0 @@ -cd src - -export PIP_NO_INDEX=true -export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" - -if [ "$SAGE_EDITABLE" = yes ]; then - # SAGE_ROOT/src/setup.py installs everything, nothing to do... - if [ "$SAGE_WHEELS" = yes ]; then - # ... except we build the wheel if requested - sdh_setup_bdist_wheel && sdh_store_wheel . - fi -else - if [ "$SAGE_WHEELS" = yes ]; then - # Modularized install via wheels - sdh_pip_install . - # else nothing to do in legacy direct installation. - fi -fi diff --git a/build/pkgs/sagemath_mcqd/spkg-install.in b/build/pkgs/sagemath_mcqd/spkg-install.in new file mode 120000 index 00000000000..e38ca3ace8b --- /dev/null +++ b/build/pkgs/sagemath_mcqd/spkg-install.in @@ -0,0 +1 @@ +../sagemath_bliss/spkg-install.in \ No newline at end of file diff --git a/build/pkgs/sagemath_meataxe/spkg-install.in b/build/pkgs/sagemath_meataxe/spkg-install.in deleted file mode 100644 index ccd53947ab0..00000000000 --- a/build/pkgs/sagemath_meataxe/spkg-install.in +++ /dev/null @@ -1,18 +0,0 @@ -cd src - -export PIP_NO_INDEX=true -export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" - -if [ "$SAGE_EDITABLE" = yes ]; then - # SAGE_ROOT/src/setup.py installs everything, nothing to do... - if [ "$SAGE_WHEELS" = yes ]; then - # ... except we build the wheel if requested - sdh_setup_bdist_wheel && sdh_store_wheel . - fi -else - if [ "$SAGE_WHEELS" = yes ]; then - # Modularized install via wheels - sdh_pip_install . - # else nothing to do in legacy direct installation. - fi -fi diff --git a/build/pkgs/sagemath_meataxe/spkg-install.in b/build/pkgs/sagemath_meataxe/spkg-install.in new file mode 120000 index 00000000000..e38ca3ace8b --- /dev/null +++ b/build/pkgs/sagemath_meataxe/spkg-install.in @@ -0,0 +1 @@ +../sagemath_bliss/spkg-install.in \ No newline at end of file diff --git a/build/pkgs/sagemath_sirocco/spkg-install.in b/build/pkgs/sagemath_sirocco/spkg-install.in deleted file mode 100644 index ccd53947ab0..00000000000 --- a/build/pkgs/sagemath_sirocco/spkg-install.in +++ /dev/null @@ -1,18 +0,0 @@ -cd src - -export PIP_NO_INDEX=true -export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" - -if [ "$SAGE_EDITABLE" = yes ]; then - # SAGE_ROOT/src/setup.py installs everything, nothing to do... - if [ "$SAGE_WHEELS" = yes ]; then - # ... except we build the wheel if requested - sdh_setup_bdist_wheel && sdh_store_wheel . - fi -else - if [ "$SAGE_WHEELS" = yes ]; then - # Modularized install via wheels - sdh_pip_install . - # else nothing to do in legacy direct installation. - fi -fi diff --git a/build/pkgs/sagemath_sirocco/spkg-install.in b/build/pkgs/sagemath_sirocco/spkg-install.in new file mode 120000 index 00000000000..e38ca3ace8b --- /dev/null +++ b/build/pkgs/sagemath_sirocco/spkg-install.in @@ -0,0 +1 @@ +../sagemath_bliss/spkg-install.in \ No newline at end of file diff --git a/build/pkgs/sagemath_tdlib/spkg-install.in b/build/pkgs/sagemath_tdlib/spkg-install.in deleted file mode 100644 index ccd53947ab0..00000000000 --- a/build/pkgs/sagemath_tdlib/spkg-install.in +++ /dev/null @@ -1,18 +0,0 @@ -cd src - -export PIP_NO_INDEX=true -export PIP_FIND_LINKS="file://$SAGE_SPKG_WHEELS" - -if [ "$SAGE_EDITABLE" = yes ]; then - # SAGE_ROOT/src/setup.py installs everything, nothing to do... - if [ "$SAGE_WHEELS" = yes ]; then - # ... except we build the wheel if requested - sdh_setup_bdist_wheel && sdh_store_wheel . - fi -else - if [ "$SAGE_WHEELS" = yes ]; then - # Modularized install via wheels - sdh_pip_install . - # else nothing to do in legacy direct installation. - fi -fi diff --git a/build/pkgs/sagemath_tdlib/spkg-install.in b/build/pkgs/sagemath_tdlib/spkg-install.in new file mode 120000 index 00000000000..e38ca3ace8b --- /dev/null +++ b/build/pkgs/sagemath_tdlib/spkg-install.in @@ -0,0 +1 @@ +../sagemath_bliss/spkg-install.in \ No newline at end of file diff --git a/configure.ac b/configure.ac index 7816aca796e..764d8a43d82 100644 --- a/configure.ac +++ b/configure.ac @@ -135,8 +135,19 @@ AC_ARG_ENABLE([editable], AC_ARG_ENABLE([wheels], [AS_HELP_STRING([--enable-wheels], [build wheels for the Sage library and update them on "sage -b"; if disabled, use "make wheels" to build wheels])], - [AC_SUBST([SAGE_WHEELS], [$enableval])], - []) + [dnl + AS_VAR_IF([SAGE_EDITABLE], [yes], [dnl + ], [dnl + AC_MSG_NOTICE([direct installation of the Sage library (--disable-editable --disable-wheels) is no longer supported; ignoring --disable-wheels]) + ]) + AC_SUBST([SAGE_WHEELS], [$enableval]) + ], [dnl + AS_VAR_IF([SAGE_EDITABLE], [yes], [dnl + AC_SUBST([SAGE_WHEELS], [no]) + ], [dnl + AC_SUBST([SAGE_WHEELS], [yes]) + ]) + ]) # Check whether we are on a supported platform AC_CANONICAL_BUILD() diff --git a/pkgs/sagemath-standard/setup.py b/pkgs/sagemath-standard/setup.py index 29c8744f910..785923c5a0e 100755 --- a/pkgs/sagemath-standard/setup.py +++ b/pkgs/sagemath-standard/setup.py @@ -52,12 +52,12 @@ from sage_setup.command.sage_build_cython import sage_build_cython from sage_setup.command.sage_build_ext import sage_build_ext -from sage_setup.command.sage_install import sage_develop, sage_install_and_clean +from sage_setup.command.sage_install import sage_develop, sage_install cmdclass = dict(build_cython=sage_build_cython, build_ext=sage_build_ext, develop=sage_develop, - install=sage_install_and_clean) + install=sage_install) ######################################################### ### Discovering Sources diff --git a/src/sage_setup/clean.py b/src/sage_setup/clean.py deleted file mode 100644 index 1b00f211d75..00000000000 --- a/src/sage_setup/clean.py +++ /dev/null @@ -1,199 +0,0 @@ -""" -Clean the Install Dir -""" -#***************************************************************************** -# Copyright (C) 2014 Volker Braun -# 2015 Jeroen Demeyer -# 2017 Erik M. Bray -# 2020-2022 Matthias Koeppe -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** - - -import importlib.util -import os - -from sage.misc.package_dir import SourceDistributionFilter -from sage_setup.find import get_extensions, installed_files_by_module - - -def _remove(file_set, module_base, to_remove): - """ - Helper to remove files from a set of filenames. - - INPUT: - - - ``file_set`` -- a set of filenames. - - - ``module_base`` -- string. Name of a Python package/module. - - - ``to_remove`` -- list/tuple/iterable of strings. Either - filenames or extensions (starting with ``'.'``) - - OUTPUT: - - This function does not return anything. The ``file_set`` parameter - is modified in place. - - EXAMPLES:: - - sage: files = set(['a/b/c.py', 'a/b/d.py', 'a/b/c.pyx']) - sage: from sage_setup.clean import _remove - sage: _remove(files, 'a.b', ['c.py', 'd.py']) - sage: files - {'a/b/c.pyx'} - - sage: files = set(['a/b/c.py', 'a/b/d.py', 'a/b/c.pyx']) - sage: _remove(files, 'a.b.c', ['.py', '.pyx']) - sage: files - {'a/b/d.py'} - """ - path = os.path.join(*module_base.split('.')) - - for filename in to_remove: - if filename.startswith('.'): - filename = path + filename - else: - filename = os.path.join(path, filename) - - remove = [filename] - - remove.append(importlib.util.cache_from_source(filename)) - file_set.difference_update(remove) - - -def _find_stale_files(site_packages, python_packages, python_modules, ext_modules, data_files, nobase_data_files=()): - """ - Find stale files - - This method lists all files installed and then subtracts the ones - which are intentionally being installed. - - EXAMPLES: - - It is crucial that only truly stale files are being found, of - course. We check that when the doctest is being run, that is, - after installation, there are no stale files:: - - sage: # needs SAGE_SRC - sage: from sage.env import SAGE_SRC, SAGE_LIB, SAGE_ROOT - sage: from sage_setup.find import _cythonized_dir - sage: cythonized_dir = _cythonized_dir(SAGE_SRC) - sage: from sage_setup.find import find_python_sources, find_extra_files - sage: python_packages, python_modules, cython_modules = find_python_sources( - ....: SAGE_SRC, ['sage', 'sage_setup']) - sage: extra_files = find_extra_files(SAGE_SRC, - ....: ['sage', 'sage_setup'], cythonized_dir, []) - sage: from importlib.metadata import files - sage: for f in files('sagemath-standard'): - ....: dir = os.path.dirname(str(f)) - ....: extra_files[dir] = extra_files.get(dir, []) - ....: extra_files[dir].append(str(f)) - sage: extra_files = list(extra_files.items()) - sage: from sage_setup.clean import _find_stale_files - - TODO: Also check extension modules:: - - sage: # needs SAGE_SRC - sage: stale_iter = _find_stale_files(SAGE_LIB, python_packages, python_modules, [], extra_files) - sage: from importlib.machinery import EXTENSION_SUFFIXES - sage: skip_extensions = tuple(EXTENSION_SUFFIXES) - sage: for f in stale_iter: - ....: if f.endswith(skip_extensions): continue - ....: if '/ext_data/' in f: continue - ....: print('Found stale file: ' + f) - """ - - PYMOD_EXTS = get_extensions('source') + get_extensions('bytecode') - CEXTMOD_EXTS = get_extensions('extension') - INIT_FILES = tuple('__init__' + x for x in PYMOD_EXTS) - - module_files = installed_files_by_module(site_packages, ['sage']) - - for mod in python_packages: - try: - files = module_files[mod] - except KeyError: - # the source module "mod" has not been previously installed, fine. - continue - _remove(files, mod, INIT_FILES) - for mod in python_modules: - try: - files = module_files[mod] - except KeyError: - continue - _remove(files, mod, PYMOD_EXTS) - for ext in ext_modules: - mod = ext.name - try: - files = module_files[mod] - except KeyError: - continue - _remove(files, mod, CEXTMOD_EXTS) - - # Convert data_files to a set - installed_files = set() - for dir, files in data_files: - for f in files: - installed_files.add(os.path.join(dir, os.path.basename(f))) - for dir, files in nobase_data_files: - for f in files: - installed_files.add(f) - - for files in module_files.values(): - for f in files: - if f not in installed_files: - yield f - - -def clean_install_dir(site_packages, python_packages, python_modules, ext_modules, data_files, nobase_data_files, *, - distributions=None, exclude_distributions=None): - """ - Delete all modules that are **not** being installed - - If you switch branches it is common to (re)move the source for an - already installed module. Subsequent rebuilds will leave the stale - module in the install directory, which can break programs that try - to import all modules. In particular, the Sphinx autodoc builder - does this and is susceptible to hard-to-reproduce failures that - way. Hence we must make sure to delete all stale modules. - - INPUT: - - - ``site_packages`` -- the root Python path where the Sage library - is being installed. - - - ``python_packages`` -- list of pure Python packages (directories - with ``__init__.py``). - - - ``python_modules`` -- list of pure Python modules. - - - ``ext_modules`` -- list of distutils ``Extension`` classes. The - output of ``cythonize``. - - - ``data_files`` -- a list of (installation directory, files) pairs, - like the ``data_files`` argument to distutils' ``setup()``. Only - the basename of the files is used. - - - ``nobase_data_files`` -- a list of (installation directory, files) - pairs. The files are expected to be in a subdirectory of the - installation directory; the filenames are used as is. - - - ``distributions`` -- (default: ``None``) if not ``None``, - should be a sequence or set of strings: only clean files whose - ``distribution`` (from a ``# sage_setup: distribution = PACKAGE`` - directive in the file) is an element of ``distributions``. - """ - distribution_filter = SourceDistributionFilter(distributions, exclude_distributions) - stale_file_iter = _find_stale_files( - site_packages, python_packages, python_modules, ext_modules, data_files, nobase_data_files) - for f in stale_file_iter: - f = os.path.join(site_packages, f) - if f in distribution_filter: - print('Cleaning up stale file: {0}'.format(f)) - os.unlink(f) diff --git a/src/sage_setup/command/sage_install.py b/src/sage_setup/command/sage_install.py index abfc142eec4..052fbecc71e 100644 --- a/src/sage_setup/command/sage_install.py +++ b/src/sage_setup/command/sage_install.py @@ -1,5 +1,5 @@ ######################################################### -### Install Jupyter kernel spec and clean stale files +### Install Jupyter kernel spec ######################################################### import os @@ -45,71 +45,3 @@ def run(self): develop.run(self) if not self.uninstall: self.install_kernel_spec() - - -class sage_clean(install): - - all_distributions = None - - def run(self): - t = time.time() - self.clean_stale_files() - log.info('Finished cleaning, time: %.2f seconds.' % (time.time() - t)) - - def clean_stale_files(self): - """ - Remove stale installed files. - - This removes files which are built/installed but which do not - exist in the Sage sources (typically because some source file - has been deleted). Files are removed from the build directory - ``build/lib-*`` and from the install directory ``site-packages``. - """ - dist = self.distribution - cmd_build_py = self.get_finalized_command("build_py") - cmd_build_cython = self.get_finalized_command("build_cython") - - # Determine all Python modules inside all packages - py_modules = [] - ordinary_packages = [] - for package in dist.packages: - package_dir = cmd_build_py.get_package_dir(package) - if os.path.exists(os.path.join(package_dir, '__init__.py')): - ordinary_packages.append(package) - py_modules.extend(cmd_build_py.find_package_modules(package, package_dir)) - # modules is a list of triples (package, module, module_file). - # Construct the complete module name from this. - py_modules = ["{0}.{1}".format(*m) for m in py_modules] - if dist.py_modules: - py_modules.extend(dist.py_modules) - - # Determine all files of package data and Cythonized package files - # example of entries of cmd_build_cython.get_cythonized_package_files(): - # ('sage/media', ['./sage/media/channels.pyx']) - data_files = cmd_build_cython.get_cythonized_package_files() - # examples of entries of build_py.data_files: - # ('sage.libs.gap', 'sage/libs/gap', 'build/lib.macosx-10.9-x86_64-3.7/sage/libs/gap', ['sage.gaprc']) - # ('sage', 'sage', 'build/lib.macosx-10.9-x86_64-3.7/sage', ['ext_data/nodoctest.py', 'ext_data/kenzo/S4.txt', ...]) - nobase_data_files = [(src_dir, [os.path.join(src_dir, filename) for filename in filenames]) - for package, src_dir, build_dir, filenames in cmd_build_py.data_files] - - # Clean install directory (usually, purelib and platlib are the same) - # and build directory. - output_dirs = [self.install_purelib, self.install_platlib, self.build_lib] - from sage_setup.clean import clean_install_dir - for output_dir in set(output_dirs): - log.info('- cleaning {0}'.format(output_dir)) - clean_install_dir(output_dir, - ordinary_packages, - py_modules, - dist.ext_modules, - data_files, - nobase_data_files, - distributions=self.all_distributions) - - -class sage_install_and_clean(sage_install, sage_clean): - - def run(self): - sage_install.run(self) - sage_clean.run(self) diff --git a/src/sage_setup/find.py b/src/sage_setup/find.py index 69bad9a3ebf..8762e08ad0f 100644 --- a/src/sage_setup/find.py +++ b/src/sage_setup/find.py @@ -342,98 +342,6 @@ def find_extra_files(src_dir, modules, cythonized_dir, special_filenames=[], *, return data_files -def installed_files_by_module(site_packages, modules=('sage',)): - """ - Find all currently installed files - - INPUT: - - - ``site_packages`` -- string. The root Python path where the Sage - library is being installed. If the path doesn't exist, returns - an empty dictionary. - - - ``modules`` -- list/tuple/iterable of strings (default: - ``('sage',)``). The top-level directory name(s) in - ``site_packages``. - - OUTPUT: - - A dictionary whose keys are module names (``'sage.module.foo'``) - and values are list of corresponding file names - ``['sage/module/foo.py', 'sage/module/foo.pyc']`` relative to - ``site_packages``. - - EXAMPLES:: - - sage: site_packages = os.path.dirname(os.path.dirname(os.path.dirname(sage.cpython.__file__))) - sage: from sage_setup.find import installed_files_by_module - sage: files_by_module = installed_files_by_module(site_packages) - sage: (f,) = files_by_module['sage.structure.sage_object']; f - 'sage/structure/sage_object...' - sage: (f1, f2) = sorted(files_by_module['sage.structure']) - sage: f1 - 'sage/structure/__init__.py' - sage: f2 - 'sage/structure/....pyc' - - Namespace packages:: - - sage: files_by_module['sage.graphs.graph_decompositions'] - set() - - This takes about 30ms with warm cache:: - - sage: timeit('installed_files_by_module(site_packages)', # random output - ....: number=1, repeat=1) - 1 loops, best of 1: 29.6 ms per loop - """ - - module_files = defaultdict(set) - module_exts = get_extensions() - - def add(module, filename, dirpath): - # Find the longest extension that matches the filename - best_ext = '' - - for ext in module_exts: - if filename.endswith(ext) and len(ext) > len(best_ext): - best_ext = ext - - if not best_ext: - return - - base = filename[:-len(best_ext)] - filename = os.path.join(dirpath, filename) - - if base != '__init__': - module += '.' + base - - module_files[module].add(filename) - - cache_filename = importlib.util.cache_from_source(filename) - if os.path.exists(cache_filename): - module_files[module].add(cache_filename) - - cwd = os.getcwd() - try: - os.chdir(site_packages) - except OSError: - return module_files - try: - for module in modules: - for dirpath, dirnames, filenames in os.walk(module): - module_dir = '.'.join(dirpath.split(os.path.sep)) - - if os.path.basename(dirpath) == '__pycache__': - continue - - for filename in filenames: - add(module_dir, filename, dirpath) - finally: - os.chdir(cwd) - return module_files - - def get_extensions(type=None): """ Returns the filename extensions for different types of Python module files.