MLBEDSW-6982: Move to setup.cfg and pyproject.toml

- Move all static information from setup.py to newly added
  pyproject.toml
- Add setup.cfg used for static information that cannot be added to
  pyproject.toml due to it still being in beta.
- Modify mlw_codec to to throw a real python exception when importing
  NumPy arrays instead of just printing them to stdout.
- Surround mlw_codec import with try catch statement to catch NumPy C
  API mismatch errors and throw them again with a more detailed message.
- Update README.md with documentation about known issue with changing
  used NumPy version after installing ethos-u-vela.

Change-Id: I1eeee5536be7c1744e30d6088f7069fbb1403e06
Signed-off-by: Raul Farkas <raul.farkas@arm.com>
diff --git a/README.md b/README.md
index ecd1322..974b0b6 100644
--- a/README.md
+++ b/README.md
@@ -189,6 +189,66 @@
 Vela to run on the Ethos-U NPU can be found at:
 <https://tfhub.dev/s?deployment-format=lite&q=quantized>
 
+## Known Issues
+
+### 1. NumPy C API version change
+
+Once ethos-u-vela is installed, the user might want to install a different NumPy
+version that is still within the dependency constraints defined in pyproject.toml.
+
+In some scenarios, doing so might prevent ethos-u-vela from functioning as
+expected due to incompatibilities between the installed NumPy C headers used in
+the mlw_codec and the current version of NumPy.
+
+**Example scenario:**
+
+In the ethos-u-vela source directory, run:
+
+```bash
+virtualenv -p 3.8 venv
+. venv/bin/activate
+pip install ethos-u-vela
+```
+
+Next, install a different NumPy version (e.g. 1.21.3)
+
+```bash
+pip install numpy==1.21.3 --force
+```
+
+Finally, run ethos-u-vela. You might get an error similar to this:
+
+```
+ImportError: NumPy C API version mismatch
+(Build-time version: 0x10, Run-time version: 0xe)
+This is a known issue most likely caused by a change in the API version in
+NumPy after installing ethos-u-vela.
+```
+
+#### Solution
+
+In order for ethos-u-vela to work with an older version of NumPy that uses
+different C APIs, you will need to install the desired NumPy version first, and
+then build ethos-u-vela with that specific NumPy version:
+
+1) Uninstall ethos-u-vela and install the desired version of NumPy
+   ```
+   pip uninstall ethos-u-vela
+   pip install numpy==1.21.3 --force
+   ```
+
+2) Install required build dependencies
+   ```
+   pip install "setuptools_scm[toml]<6" wheel
+   ```
+
+3) Install ethos-u-vela without build isolation. Not using build isolation
+   ensures that the correct version of NumPy is used when copying the C headers
+   in mlw_codec during the build process.
+   ```
+   pip install ethos-u-vela --no-build-isolation --no-cache-dir
+   ```
+
 ## APIs
 
 Please see [Vela External APIs](API.md).
diff --git a/ethosu/mlw_codec/mlw_codecmodule.c b/ethosu/mlw_codec/mlw_codecmodule.c
index 61ae6a4..8c540d6 100644
--- a/ethosu/mlw_codec/mlw_codecmodule.c
+++ b/ethosu/mlw_codec/mlw_codecmodule.c
@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: Copyright 2020-2021 Arm Limited and/or its affiliates <open-source-office@arm.com>
+ * SPDX-FileCopyrightText: Copyright 2020-2021, 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -15,7 +15,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include <numpy/ndarrayobject.h>
@@ -307,7 +306,19 @@
 
 PyMODINIT_FUNC PyInit_mlw_codec(void)
 {
+    PyObject *ptype, *pvalue, *ptraceback;
     PyObject* ret = PyModule_Create(&mlw_codecmodule);
-    import_array();
+    if (_import_array() < 0)
+    {
+      // Fetch currently set error
+      PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+      // Extract the error message
+      const char *pStrErrorMessage = PyUnicode_AsUTF8(pvalue);
+      // Re-format error message to start with "mlw_codec Error: " so it is
+      // clearer it comes from mlw_codec.
+      PyErr_Format(PyExc_RuntimeError, "mlw_codec error: %s", pStrErrorMessage);
+      return NULL;
+    }
+
     return ret;
 }
diff --git a/ethosu/vela/weight_compressor.py b/ethosu/vela/weight_compressor.py
index e3e318c..e56cc5e 100644
--- a/ethosu/vela/weight_compressor.py
+++ b/ethosu/vela/weight_compressor.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: Copyright 2020-2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# SPDX-FileCopyrightText: Copyright 2020-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 #
 # SPDX-License-Identifier: Apache-2.0
 #
@@ -37,7 +37,28 @@
 from .tensor import Tensor
 from .tensor import TensorFormat
 from .tensor import TensorPurpose
-from ethosu import mlw_codec
+
+# Handle any errors thrown by NumPy while importing mlw_codec module
+try:
+    from ethosu import mlw_codec
+except RuntimeError as ex:
+    if "mlw_codec error: module compiled against API version" in str(ex):
+        # Extract API versions from error message
+        matches = [s for s in str(ex).split() if "0x" in s]
+        if len(matches) == 2:
+            # Raise new exception with more detailed message
+            raise ImportError(  # pylint: disable=W0707
+                "NumPy C API version mismatch "
+                f"(Build-time version: {matches[0]}, "
+                f"Run-time version: {matches[1]})"
+                "\nThis is a known issue most likely caused by a change in the API "
+                "version in NumPy after installing ethos-u-vela.\nYou can find more "
+                "information about the issue and possible solutions in the "
+                "'Known Issues' section at https://review.mlplatform.org/"
+                "plugins/gitiles/ml/ethos-u/ethos-u-vela/+/refs/heads/main/"
+                "README.md#known-issues"
+            )
+    raise
 
 
 # Contains meta info for a weight compression. If two tensors have identical weight compression config,
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..d8cbe66
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,56 @@
+# SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the License); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[project]
+name = "ethos-u-vela"
+description = "Neural network model compiler for Arm Ethos-U NPUs"
+requires-python = "~=3.7"
+authors = [{name = "Arm Ltd", email = "mlg-vela@arm.com"}]
+license = {text= "Apache License 2.0"}
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "Intended Audience :: Developers",
+    "License :: OSI Approved :: Apache Software License",
+    "Operating System :: POSIX :: Linux",
+    "Operating System :: Microsoft :: Windows :: Windows 10",
+    "Programming Language :: C",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3.7",
+    "Topic :: Scientific/Engineering :: Artificial Intelligence",
+    "Topic :: Software Development :: Compilers",
+]
+keywords = ["ethos-u", "vela compiler", "tflite", "npu"]
+dependencies = [
+    "flatbuffers==2.0.7",
+    "numpy<=1.21.3; python_version<='3.7'",
+    "numpy; python_version>'3.7'",
+    "lxml>=4.5.1"
+]
+dynamic = ["readme", "version"]
+
+[project.urls]
+Homepage = "https://git.mlplatform.org/ml/ethos-u/ethos-u-vela.git/"
+
+[project.scripts]
+vela = "ethosu.vela.vela:main"
+
+[build-system]
+requires = [
+    "numpy<=1.21.3; python_version<='3.7'",
+    "numpy; python_version>'3.7'",
+    "setuptools_scm[toml]<6"
+]
+build-backend = "setuptools.build_meta"
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..5c63e15
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,27 @@
+# SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed under the Apache License, Version 2.0 (the License); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[options]
+packages =
+    ethosu
+    ethosu.vela
+    ethosu.vela.ethos_u55_regs
+    ethosu.vela.tflite
+    ethosu.vela.tosa
+    ethosu.mlw_codec
+
+[options.package_data]
+ethosu = config_files/*/*.ini
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 69a115a..29df63b 100644
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: Copyright 2020-2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# SPDX-FileCopyrightText: Copyright 2020-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
 #
 # SPDX-License-Identifier: Apache-2.0
 #
@@ -61,46 +61,9 @@
 )
 
 setup(
-    name="ethos-u-vela",
     use_scm_version=True,
-    description="Neural network model compiler for Arm Ethos-U NPUs",
     long_description=long_description,
     long_description_content_type="text/markdown",
-    url="https://git.mlplatform.org/ml/ethos-u/ethos-u-vela.git/",
-    author="Arm Ltd.",
-    author_email="mlg-vela@arm.com",
-    license="Apache License 2.0",
-    classifiers=[
-        "Development Status :: 5 - Production/Stable",
-        "Intended Audience :: Developers",
-        "License :: OSI Approved :: Apache Software License",
-        "Operating System :: POSIX :: Linux",
-        "Operating System :: Microsoft :: Windows :: Windows 10",
-        "Programming Language :: C",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.7",
-        "Topic :: Scientific/Engineering :: Artificial Intelligence",
-        "Topic :: Software Development :: Compilers",
-    ],
-    keywords=["ethos-u", "vela compiler", "tflite", "npu"],
-    packages=[
-        "ethosu",
-        "ethosu.vela",
-        "ethosu.vela.ethos_u55_regs",
-        "ethosu.vela.tflite",
-        "ethosu.vela.tosa",
-        "ethosu.mlw_codec",
-    ],
-    package_data={"ethosu": ["config_files/*/*.ini"]},
-    python_requires="~=3.7",
-    install_requires=[
-        "flatbuffers==2.0.7",
-        "numpy<=1.21.3; python_version<='3.7'",
-        "numpy; python_version>'3.7'",
-        "lxml>=4.5.1",
-    ],
-    entry_points={"console_scripts": ["vela = ethosu.vela.vela:main"]},
     ext_modules=[mlw_module],
     cmdclass={"build_ext": BuildExtension},  # type: ignore[dict-item]
-    setup_requires=["numpy<=1.21.3; python_version<='3.7'", "numpy; python_version>'3.7'", "setuptools_scm<6.0"],
 )