From e41aa50f5b66414e98c40cc85ba84e372af54fc8 Mon Sep 17 00:00:00 2001 From: Matthias Diener Date: Fri, 10 May 2024 11:05:42 -0500 Subject: [PATCH] specify config in pyproject.toml --- .conda-ci-build-configure.sh | 6 - .github/workflows/ci.yml | 14 +- aksetup_helper.py | 1013 ---------------------------------- configure.py | 6 - pyproject.toml | 8 + 5 files changed, 15 insertions(+), 1032 deletions(-) delete mode 100644 aksetup_helper.py delete mode 100755 configure.py diff --git a/.conda-ci-build-configure.sh b/.conda-ci-build-configure.sh index 7df19ec6d..e69de29bb 100644 --- a/.conda-ci-build-configure.sh +++ b/.conda-ci-build-configure.sh @@ -1,6 +0,0 @@ -case $(uname) in - MINGW*|MSYS*) python ./configure.py --cl-inc-dir="$CONDA_PREFIX/Library/include" \ - --cl-lib-dir="$CONDA_PREFIX/Library/lib";; - *) python ./configure.py --cl-inc-dir="$CONDA_PREFIX/include" \ - --cl-lib-dir="$CONDA_PREFIX/lib";; -esac diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8d6128be..3d8b41d7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: run: | curl -L -O https://tiker.net/ci-support-v0 . ci-support-v0 - ./configure.py --cl-use-shipped-ext + # ./configure.py --cl-use-shipped-ext build_py_project_in_conda_env python -m pip install mypy importlib-resources @@ -72,7 +72,7 @@ jobs: run: | curl -L -O https://tiker.net/ci-support-v0 . ci-support-v0 - ./configure.py --cl-use-shipped-ext + # ./configure.py --cl-use-shipped-ext build_py_project_in_conda_env test_py_project @@ -88,7 +88,7 @@ jobs: curl -L -O https://tiker.net/ci-support-v0 . ci-support-v0 - ./configure.py --cl-use-shipped-ext + # ./configure.py --cl-use-shipped-ext build_py_project_in_conda_env test_py_project @@ -110,7 +110,7 @@ jobs: curl -L -O https://tiker.net/ci-support-v0 . ci-support-v0 - ./configure.py --cl-use-shipped-ext + # ./configure.py --cl-use-shipped-ext build_py_project_in_conda_env test_py_project @@ -127,7 +127,7 @@ jobs: curl -L -O https://tiker.net/ci-support-v0 . ci-support-v0 - ./configure.py --cl-libname=OpenCL + # ./configure.py --cl-libname=OpenCL build_py_project_in_conda_env test_py_project @@ -146,7 +146,7 @@ jobs: curl -L -O https://tiker.net/ci-support-v0 . ci-support-v0 - ./configure.py --cl-use-shipped-ext + # ./configure.py --cl-use-shipped-ext build_py_project_in_conda_env build_docs @@ -181,7 +181,7 @@ jobs: . ci-support-v0 TEST_ENV_ROOT="$(pwd)/$DOWNSTREAM_PROJECT/.conda-root/envs/testing" - ./configure.py --cl-inc-dir="$TEST_ENV_ROOT/include" --cl-lib-dir="$TEST_ENV_ROOT/lib" + # ./configure.py --cl-inc-dir="$TEST_ENV_ROOT/include" --cl-lib-dir="$TEST_ENV_ROOT/lib" git add -f siteconf.py prepare_downstream_build "https://github.com/inducer/$DOWNSTREAM_PROJECT.git" diff --git a/aksetup_helper.py b/aksetup_helper.py deleted file mode 100644 index db613790e..000000000 --- a/aksetup_helper.py +++ /dev/null @@ -1,1013 +0,0 @@ -import os -import sys - - -try: - from setuptools import Extension - from setuptools.command.build_ext import \ - build_ext as BaseBuildExtCommand # noqa: N812 - -except ImportError: - class Extension: - pass - - class BaseBuildExtCommand: - pass - - -def count_down_delay(delay): - from time import sleep - while delay: - sys.stdout.write("Continuing in %d seconds... \r" % delay) - sys.stdout.flush() - delay -= 1 - sleep(1) - print("") - - -DASH_SEPARATOR = 75 * "-" - - -def setup(*args, **kwargs): - from setuptools import setup - try: - setup(*args, **kwargs) - except KeyboardInterrupt: - raise - except SystemExit: - raise - except Exception: - print(DASH_SEPARATOR) - print("Sorry, your build failed. Try rerunning configure.py with " - "different options.") - print(DASH_SEPARATOR) - raise - - -def get_numpy_incpath(): - from importlib.util import find_spec - from os.path import dirname, exists, join - origin = find_spec("numpy").origin - if origin is None: - raise RuntimeError("origin of numpy package not found") - - pathname = dirname(origin) - for p in [ - join(pathname, "_core", "include"), # numpy 2 onward - join(pathname, "core", "include"), # numpy prior to 2 - ]: - if exists(join(p, "numpy", "arrayobject.h")): - return p - - raise RuntimeError("no valid path for numpy found") - - -class NumpyExtension(Extension): - # nicked from - # http://mail.python.org/pipermail/distutils-sig/2007-September/008253.html - # solution by Michael Hoffmann - def __init__(self, *args, **kwargs): - Extension.__init__(self, *args, **kwargs) - self._include_dirs = self.include_dirs - del self.include_dirs # restore overwritten property - - def get_additional_include_dirs(self): - return [get_numpy_incpath()] - - def get_include_dirs(self): - return self._include_dirs + self.get_additional_include_dirs() - - def set_include_dirs(self, value): - self._include_dirs = value - - def del_include_dirs(self): - pass - - include_dirs = property(get_include_dirs, set_include_dirs, del_include_dirs) - - -class ExtensionUsingNumpy(Extension): - """Unlike :class:`NumpyExtension`, this class does not require numpy to be - importable upon extension module creation, allowing ``setup_requires=["numpy"]`` - to work. On the other hand, it requires the use of:: - - setup(..., - cmdclass={'build_ext': NumpyBuildExtCommand}) - - or - - setup(..., - cmdclass={'build_ext': PybindBuildExtCommand}) - """ - - -class NumpyBuildExtCommand(BaseBuildExtCommand): - def build_extension(self, extension): - # We add the numpy include dir right before building the - # extension, in order to avoid having to import numpy when - # the setup script is imported, which would prevent - # installation before manual installation of numpy. - if isinstance(extension, ExtensionUsingNumpy): - numpy_incpath = get_numpy_incpath() - if numpy_incpath not in extension.include_dirs: - extension.include_dirs.append(numpy_incpath) - - BaseBuildExtCommand.build_extension(self, extension) - - -# {{{ tools - -def flatten(lst): - """For an iterable of sub-iterables, generate each member of each - sub-iterable in turn, i.e. a flattened version of that super-iterable. - - Example: Turn [[a,b,c],[d,e,f]] into [a,b,c,d,e,f]. - """ - for sublist in lst: - for j in sublist: - yield j - - -def humanize(sym_str): - words = sym_str.lower().replace("_", " ").split(" ") - return " ".join([word.capitalize() for word in words]) - -# }}} - - -# {{{ siteconf handling - -def get_config(schema=None, warn_about_no_config=True): - if schema is None: - from setup import get_config_schema - schema = get_config_schema() - - if (not schema.have_config() and not schema.have_global_config() - and warn_about_no_config): - print("*************************************************************") - print("*** I have detected that you have not run configure.py.") - print("*************************************************************") - print("*** Additionally, no global config files were found.") - print("*** I will go ahead with the default configuration.") - print("*** In all likelihood, this will not work out.") - print("*** ") - print("*** See README_SETUP.txt for more information.") - print("*** ") - print("*** If the build does fail, just re-run configure.py with the") - print("*** correct arguments, and then retry. Good luck!") - print("*************************************************************") - print("*** HIT Ctrl-C NOW IF THIS IS NOT WHAT YOU WANT") - print("*************************************************************") - - count_down_delay(delay=10) - - config = expand_options(schema.read_config()) - schema.update_config_from_and_modify_command_line(config, sys.argv) - return config - - -def hack_distutils(debug=False, fast_link=True, what_opt=3): - # hack distutils.sysconfig to eliminate debug flags - # stolen from mpi4py - - def remove_prefixes(optlist, bad_prefixes): - for bad_prefix in bad_prefixes: - for i, flag in enumerate(optlist): - if flag.startswith(bad_prefix): - optlist.pop(i) - break - return optlist - - if not sys.platform.lower().startswith("win"): - from distutils import sysconfig - - cvars = sysconfig.get_config_vars() - - bad_prefixes = ["-g", "-O", "-Wstrict-prototypes", "-DNDEBUG"] - - cflags = cvars.get("OPT") - if cflags: - cflags = remove_prefixes(cflags.split(), bad_prefixes) - if debug: - cflags.append("-g") - else: - if what_opt is None: - pass - else: - cflags.append("-O%s" % what_opt) - cflags.append("-DNDEBUG") - - cvars["OPT"] = str.join(" ", cflags) - - cflags = cvars.get("CONFIGURE_CFLAGS") - if cflags: - cflags = remove_prefixes(cflags.split(), bad_prefixes) - cvars["CONFIGURE_CFLAGS"] = str.join(" ", cflags) - - if "BASECFLAGS" in cvars: - cvars["CFLAGS"] = cvars["BASECFLAGS"] + " " + cvars.get("OPT", "") - else: - assert "CFLAGS" in cvars - - if fast_link: - for varname in ["LDSHARED", "BLDSHARED"]: - ldsharedflags = cvars.get(varname) - if ldsharedflags: - ldsharedflags = remove_prefixes(ldsharedflags.split(), - ["-Wl,-O"]) - cvars[varname] = str.join(" ", ldsharedflags) - -# }}} - - -# {{{ configure guts - -def default_or(a, b): - if a is None: - return b - else: - return a - - -def expand_str(s, options): - import re - - def my_repl(match): - sym = match.group(1) - try: - repl = options[sym] - except KeyError: - from os import environ - repl = environ[sym] - - return expand_str(repl, options) - - return re.subn(r"\$\{([a-zA-Z0-9_]+)\}", my_repl, s)[0] - - -def expand_value(v, options): - if isinstance(v, str): - return expand_str(v, options) - elif isinstance(v, list): - result = [] - for i in v: - try: - exp_i = expand_value(i, options) - except Exception: - pass - else: - result.append(exp_i) - - return result - else: - return v - - -def expand_options(options): - return dict( - (k, expand_value(v, options)) for k, v in options.items()) - - -class ConfigSchema: - def __init__(self, options, conf_file="siteconf.py", conf_dir=os.path.dirname(__file__)): - self.optdict = dict((opt.name, opt) for opt in options) - self.options = options - self.conf_dir = conf_dir - self.conf_file = conf_file - - from os.path import expanduser - self.user_conf_file = expanduser("~/.aksetup-defaults.py") - - if not sys.platform.lower().startswith("win"): - self.global_conf_file = "/etc/aksetup-defaults.py" - else: - self.global_conf_file = None - - def get_conf_file(self): - import os - return os.path.join(self.conf_dir, self.conf_file) - - def set_conf_dir(self, conf_dir): - self.conf_dir = conf_dir - - def get_default_config(self): - return dict((opt.name, opt.default) for opt in self.options) - - def read_config_from_pyfile(self, filename): - result = {} - filevars = {} - infile = open(filename, "r") - try: - contents = infile.read() - finally: - infile.close() - - exec(compile(contents, filename, "exec"), filevars) - - for key, value in filevars.items(): - if key in self.optdict: - result[key] = value - - return result - - def update_conf_file(self, filename, config): - result = {} - filevars = {} - - try: - exec(compile(open(filename, "r").read(), filename, "exec"), filevars) - except IOError: - pass - - if "__builtins__" in filevars: - del filevars["__builtins__"] - - for key, value in config.items(): - if value is not None: - filevars[key] = value - - keys = list(filevars.keys()) - keys.sort() - - outf = open(filename, "w") - for key in keys: - outf.write("%s = %s\n" % (key, repr(filevars[key]))) - outf.close() - - return result - - def update_user_config(self, config): - self.update_conf_file(self.user_conf_file, config) - - def update_global_config(self, config): - if self.global_conf_file is not None: - self.update_conf_file(self.global_conf_file, config) - - def get_default_config_with_files(self): - result = self.get_default_config() - - import os - - confignames = [] - if self.global_conf_file is not None: - confignames.append(self.global_conf_file) - confignames.append(self.user_conf_file) - - for fn in confignames: - if os.access(fn, os.R_OK): - result.update(self.read_config_from_pyfile(fn)) - - return result - - def have_global_config(self): - import os - result = os.access(self.user_conf_file, os.R_OK) - - if self.global_conf_file is not None: - result = result or os.access(self.global_conf_file, os.R_OK) - - return result - - def have_config(self): - import os - return os.access(self.get_conf_file(), os.R_OK) - - def update_from_python_snippet(self, config, py_snippet, filename): - filevars = {} - exec(compile(py_snippet, filename, "exec"), filevars) - - for key, value in filevars.items(): - if key in self.optdict: - config[key] = value - elif key == "__builtins__": - pass - else: - raise KeyError("invalid config key in %s: %s" % ( - filename, key)) - - def update_config_from_and_modify_command_line(self, config, argv): - cfg_prefix = "--conf:" - - i = 0 - while i < len(argv): - arg = argv[i] - - if arg.startswith(cfg_prefix): - del argv[i] - self.update_from_python_snippet( - config, arg[len(cfg_prefix):], "") - else: - i += 1 - - return config - - def read_config(self): - import os - cfile = self.get_conf_file() - - result = self.get_default_config_with_files() - if os.access(cfile, os.R_OK): - with open(cfile, "r") as inf: - py_snippet = inf.read() - self.update_from_python_snippet(result, py_snippet, cfile) - - return result - - def add_to_configparser(self, parser, def_config=None): - if def_config is None: - def_config = self.get_default_config_with_files() - - for opt in self.options: - default = default_or(def_config.get(opt.name), opt.default) - opt.add_to_configparser(parser, default) - - def get_from_configparser(self, options): - result = {} - for opt in self.options: - result[opt.name] = opt.take_from_configparser(options) - return result - - def write_config(self, config): - outf = open(self.get_conf_file(), "w") - for opt in self.options: - value = config[opt.name] - if value is not None: - outf.write("%s = %s\n" % (opt.name, repr(config[opt.name]))) - outf.close() - - def make_substitutions(self, config): - return dict((opt.name, opt.value_to_str(config[opt.name])) - for opt in self.options) - - -class Option(object): - def __init__(self, name, default=None, help=None): - self.name = name - self.default = default - self.help = help - - def as_option(self): - return self.name.lower().replace("_", "-") - - def metavar(self): - last_underscore = self.name.rfind("_") - return self.name[last_underscore+1:] - - def get_help(self, default): - result = self.help - if self.default: - result += " (default: %s)" % self.value_to_str( - default_or(default, self.default)) - return result - - def value_to_str(self, default): - return default - - def add_to_configparser(self, parser, default=None): - default = default_or(default, self.default) - default_str = self.value_to_str(default) - parser.add_option( - "--" + self.as_option(), dest=self.name, - default=default_str, - metavar=self.metavar(), help=self.get_help(default)) - - def take_from_configparser(self, options): - return getattr(options, self.name) - - -class Switch(Option): - def add_to_configparser(self, parser, default=None): - if not isinstance(self.default, bool): - raise ValueError("Switch options must have a default") - - if default is None: - default = self.default - - option_name = self.as_option() - - if default: - option_name = "no-" + option_name - action = "store_false" - else: - action = "store_true" - - parser.add_option( - "--" + option_name, - dest=self.name, - help=self.get_help(default), - default=default, - action=action) - - -class StringListOption(Option): - def value_to_str(self, default): - if default is None: - return None - - return ",".join([str(el).replace(",", r"\,") for el in default]) - - def get_help(self, default): - return Option.get_help(self, default) + " (several ok)" - - def take_from_configparser(self, options): - opt = getattr(options, self.name) - if opt is None: - return None - else: - if opt: - import re - sep = re.compile(r"(?