Repository: conda/conda-build

Issue:
`numpy` version for conda-build is pointing to 1.16 on MacOS (M1 only)
### Checklist

- [X] I added a descriptive title
- [X] I searched open reports and couldn't find a duplicate

### What happened?

When running `tests/test_variants.py::test_numpy_used_variable_looping`, the following error pops up:

```
    raise DependencyNeedsBuildingError(exc, subdir=subdir)
conda_build.exceptions.DependencyNeedsBuildingError: Unsatisfiable dependencies for platform osx-arm64: {'numpy=1.16'}
```

`conda-build/tests/test-recipes/variants/numpy_used/conda_build_config.yaml` contains the following:

```
[snippet]
numpy:
    - 1.16
    - 1.19
```

We should either upgrade the `numpy` version for M1 Mac systems or we need to skip this test for now; after the fix, we'll remove the `skipif` decorator.


### Additional Context

Release notes from `numpy`'s latest version for M1 support: https://numpy.org/doc/stable/release/1.21.4-notes.html


Discussion:
@beeankha`numpy` should be **1.19** for `osx-arm64` platform, see https://github.com/AnacondaRecipes/aggregate/blob/b655086f99139bf951d7a59ce1315249d969c58d/conda_build_config.yaml#L158-L162

Resolving patch:
diff --git a/conda_build/bdist_conda.py b/conda_build/bdist_conda.py
--- a/conda_build/bdist_conda.py
+++ b/conda_build/bdist_conda.py
@@ -8,9 +8,10 @@
 import sys
 import time
 from collections import defaultdict
-from distutils.command.install import install
-from distutils.dist import Distribution
-from distutils.errors import DistutilsGetoptError, DistutilsOptionError
+
+from setuptools.command.install import install
+from setuptools.dist import Distribution
+from setuptools.errors import BaseError, OptionError
 
 from conda_build import api
 from conda_build.build import handle_anaconda_upload
@@ -22,6 +23,10 @@
 # TODO: Add support for all the options that conda build has
 
 
+class GetoptError(BaseError):
+    """The option table provided to 'fancy_getopt()' is bogus."""
+
+
 class CondaDistribution(Distribution):
     """
     Distribution subclass that supports bdist_conda options
@@ -29,9 +34,6 @@ class CondaDistribution(Distribution):
     This class is required if you want to pass any bdist_conda specific
     options to setup().  To use, set distclass=CondaDistribution in setup().
 
-    **NOTE**: If you use setuptools, you must import setuptools before
-    importing distutils.commands.bdist_conda.
-
     Options that can be passed to setup() (must include
     distclass=CondaDistribution):
 
@@ -115,7 +117,7 @@ def initialize_options(self):
     def finalize_options(self):
         opt_dict = self.distribution.get_option_dict("install")
         if self.prefix:
-            raise DistutilsOptionError("--prefix is not allowed")
+            raise OptionError("--prefix is not allowed")
         opt_dict["prefix"] = ("bdist_conda", self.config.host_prefix)
         super().finalize_options()
 
@@ -184,7 +186,7 @@ def run(self):
                     c.read_file(StringIO(newstr))
                 except Exception as err:
                     # This seems to be the best error here
-                    raise DistutilsGetoptError(
+                    raise GetoptError(
                         "ERROR: entry-points not understood: "
                         + str(err)
                         + "\nThe string was"
@@ -203,7 +205,7 @@ def run(self):
                             entry_points[section] = None
 
             if not isinstance(entry_points, dict):
-                raise DistutilsGetoptError(
+                raise GetoptError(
                     "ERROR: Could not add entry points. They were:\n" + entry_points
                 )
             else:
diff --git a/conda_build/variants.py b/conda_build/variants.py
--- a/conda_build/variants.py
+++ b/conda_build/variants.py
@@ -19,7 +19,7 @@
 
 DEFAULT_VARIANTS = {
     "python": f"{sys.version_info.major}.{sys.version_info.minor}",
-    "numpy": "1.21",
+    "numpy": "1.22",
     # this one actually needs to be pretty specific.  The reason is that cpan skeleton uses the
     #    version to say what's in their standard library.
     "perl": "5.26.2",
diff --git a/conda_build/windows.py b/conda_build/windows.py
--- a/conda_build/windows.py
+++ b/conda_build/windows.py
@@ -10,8 +10,10 @@
 # Leverage the hard work done by setuptools/distutils to find vcvarsall using
 # either the registry or the VS**COMNTOOLS environment variable
 try:
-    from distutils.msvc9compiler import WINSDK_BASE, Reg
-    from distutils.msvc9compiler import find_vcvarsall as distutils_find_vcvarsall
+    from setuptools._distutils.msvc9compiler import WINSDK_BASE, Reg
+    from setuptools._distutils.msvc9compiler import (
+        find_vcvarsall as distutils_find_vcvarsall,
+    )
 except:
     # Allow some imports to work for cross or CONDA_SUBDIR usage.
     pass


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -63,14 +63,14 @@ jobs:
       fail-fast: false
       matrix:
         # test all lower versions (w/ stable conda) and upper version (w/ canary conda)
-        python-version: ['3.8', '3.9']
+        python-version: ['3.8', '3.9', '3.10']
         conda-version: [release]
         test-type: [serial, parallel]
         include:
-          - python-version: '3.10'
+          - python-version: '3.11'
             conda-version: canary
             test-type: serial
-          - python-version: '3.10'
+          - python-version: '3.11'
             conda-version: canary
             test-type: parallel
     env:
@@ -172,10 +172,10 @@ jobs:
         conda-version: [release]
         test-type: [serial, parallel]
         include:
-          - python-version: '3.10'
+          - python-version: '3.11'
             conda-version: canary
             test-type: serial
-          - python-version: '3.10'
+          - python-version: '3.11'
             conda-version: canary
             test-type: parallel
     env:
@@ -284,10 +284,10 @@ jobs:
         conda-version: [release]
         test-type: [serial, parallel]
         include:
-          - python-version: '3.10'
+          - python-version: '3.11'
             conda-version: canary
             test-type: serial
-          - python-version: '3.10'
+          - python-version: '3.11'
             conda-version: canary
             test-type: parallel
     env:
diff --git a/tests/requirements.txt b/tests/requirements.txt
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -20,7 +20,6 @@ pkginfo
 psutil
 py  # https://github.com/ContinuumIO/anaconda-issues/issues/13198
 py-lief
-pycrypto
 pyflakes
 pytest
 pytest-cov
diff --git a/tests/test-recipes/metadata/_script_win_creates_exe/setup.py b/tests/test-recipes/metadata/_script_win_creates_exe/setup.py
--- a/tests/test-recipes/metadata/_script_win_creates_exe/setup.py
+++ b/tests/test-recipes/metadata/_script_win_creates_exe/setup.py
@@ -1,4 +1,4 @@
-from distutils.core import setup
+from setuptools import setup
 setup(name='foobar',
       version='1.0',
       scripts=['test-script']
diff --git a/tests/test-recipes/metadata/_script_win_creates_exe_garbled/setup.py b/tests/test-recipes/metadata/_script_win_creates_exe_garbled/setup.py
--- a/tests/test-recipes/metadata/_script_win_creates_exe_garbled/setup.py
+++ b/tests/test-recipes/metadata/_script_win_creates_exe_garbled/setup.py
@@ -1,4 +1,4 @@
-from distutils.core import setup
+from setuptools import setup
 setup(name='foobar',
       version='1.0',
       scripts=['test-script']
diff --git a/tests/test-recipes/metadata/jinja_load_setuptools/setup.py b/tests/test-recipes/metadata/jinja_load_setuptools/setup.py
--- a/tests/test-recipes/metadata/jinja_load_setuptools/setup.py
+++ b/tests/test-recipes/metadata/jinja_load_setuptools/setup.py
@@ -1,4 +1,4 @@
-from distutils.core import setup
+from setuptools import setup
 
 VERSION = '1.test'
 
diff --git a/tests/test-recipes/metadata/jinja_load_yaml/environment.yml b/tests/test-recipes/metadata/jinja_load_yaml/environment.yml
--- a/tests/test-recipes/metadata/jinja_load_yaml/environment.yml
+++ b/tests/test-recipes/metadata/jinja_load_yaml/environment.yml
@@ -2,6 +2,6 @@ name: foo
 channels:
   - defaults
 dependencies:
-  - python=3.10
+  - python
   - tqdm
 prefix: /home/abraham/.conda/envs/foo
diff --git a/tests/test-recipes/metadata/state_variables/setup.py b/tests/test-recipes/metadata/state_variables/setup.py
--- a/tests/test-recipes/metadata/state_variables/setup.py
+++ b/tests/test-recipes/metadata/state_variables/setup.py
@@ -1,6 +1,5 @@
 import os
 from setuptools import setup
-# from distutils.core import setup
 
 if not os.getenv("CONDA_BUILD_STATE") == "RENDER":
     raise ValueError("Conda build state not set correctly")
diff --git a/tests/test-recipes/test-package/setup.py b/tests/test-recipes/test-package/setup.py
--- a/tests/test-recipes/test-package/setup.py
+++ b/tests/test-recipes/test-package/setup.py
@@ -1,6 +1,5 @@
 import sys
 from setuptools import setup
-# from distutils.core import setup
 
 # test with an old version of Python that we'll never normally use
 if sys.version_info[:2] == (3, 5):
diff --git a/tests/test-recipes/variants/numpy_used/conda_build_config.yaml b/tests/test-recipes/variants/numpy_used/conda_build_config.yaml
--- a/tests/test-recipes/variants/numpy_used/conda_build_config.yaml
+++ b/tests/test-recipes/variants/numpy_used/conda_build_config.yaml
@@ -2,5 +2,5 @@ python:
     - 3.8
     - 3.9
 numpy:
-    - 1.16
     - 1.19
+    - 1.22
diff --git a/tests/test_api_build.py b/tests/test_api_build.py
--- a/tests/test_api_build.py
+++ b/tests/test_api_build.py
@@ -430,7 +430,7 @@ def test_checkout_tool_as_dependency(testing_workdir, testing_config, monkeypatc
 platforms = ["64" if sys.maxsize > 2**32 else "32"]
 if sys.platform == "win32":
     platforms = sorted({"32", *platforms})
-    compilers = ["3.9", "3.10"]
+    compilers = ["3.10", "3.11"]
     msvc_vers = ["14.0"]
 else:
     msvc_vers = []
diff --git a/tests/test_api_render.py b/tests/test_api_render.py
--- a/tests/test_api_render.py
+++ b/tests/test_api_render.py
@@ -213,7 +213,7 @@ def test_noarch_with_no_platform_deps(testing_workdir, testing_config):
 def test_setting_condarc_vars_with_env_var_expansion(testing_workdir):
     os.makedirs("config")
     # python won't be used - the stuff in the recipe folder will override it
-    python_versions = ["2.6", "3.4", "3.10"]
+    python_versions = ["2.6", "3.4", "3.11"]
     config = {"python": python_versions, "bzip2": ["0.9", "1.0"]}
     with open(os.path.join("config", "conda_build_config.yaml"), "w") as f:
         yaml.dump(config, f, default_flow_style=False)
diff --git a/tests/test_variants.py b/tests/test_variants.py
--- a/tests/test_variants.py
+++ b/tests/test_variants.py
@@ -59,7 +59,7 @@ def test_python_variants(testing_workdir, testing_config, as_yaml):
     python 3.5 -> python >=3.5,<3.6.0a0
     otherPackages 3.5 -> otherPackages 3.5
     """
-    variants = {"python": ["3.9", "3.10"]}
+    variants = {"python": ["3.10", "3.11"]}
     testing_config.ignore_system_config = True
 
     # write variants to disk
@@ -86,7 +86,7 @@ def test_python_variants(testing_workdir, testing_config, as_yaml):
     assert {
         *metadata[0][0].meta["requirements"]["run"],
         *metadata[1][0].meta["requirements"]["run"],
-    } == {"python >=3.9,<3.10.0a0", "python >=3.10,<3.11.0a0"}
+    } == {"python >=3.10,<3.11.0a0", "python >=3.11,<3.12.0a0"}
 
 
 def test_use_selectors_in_variants(testing_workdir, testing_config):
@@ -493,11 +493,6 @@ def test_target_platform_looping():
     assert len(outputs) == 2
 
 
-@pytest.mark.skipif(
-    on_mac and platform.machine() == "arm64",
-    reason="Unsatisfiable dependencies for M1 MacOS systems: {'numpy=1.16'}",
-)
-# TODO Remove the above skip decorator once https://github.com/conda/conda-build/issues/4717 is resolved
 def test_numpy_used_variable_looping():
     outputs = api.get_output_file_paths(os.path.join(variants_dir, "numpy_used"))
     assert len(outputs) == 4