diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1300c1d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +name: CI + +on: + pull_request: + branches: + - master + push: + branches: + - master + +env: + DEFAULT_PYTHON_VERSION: "3.10" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.DEFAULT_PYTHON_VERSION }} + + - name: Install requirements + run: | + pip install -r requirements.txt + + - name: Debug info + run: | + pip freeze + + - name: Run tests + run: | + pytest . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a509724 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# build artifacts + +.eggs/ +.mypy_cache +arrayfire.egg-info/ +build/ +dist/ + + +# dev tools + +venv/ +.vscode/ + + +# jupyter notebooks + +.ipynb_checkpoints + + +# miscellaneous + +.cache/ +doc/_build/ +*.swp +.DS_Store + + +# python + +*.pyc +*.pyo +__pycache__ + + +# testing and continuous integration + +.coverage +.pytest_cache/ + +# documentation build artifacts + +docs/*.md +docs/api +site/ +mkdocs.yml diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..67dc44b --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +include LICENSE +include README.md +recursive-include arrayfire * +global-exclude .DS_Store *.py[cod] +prune **/__pycache__ +prune **/.mypy_cache diff --git a/arrayfire/__init__.py b/arrayfire/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/arrayfire/py.typed b/arrayfire/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/arrayfire/version.py b/arrayfire/version.py new file mode 100644 index 0000000..ae862ac --- /dev/null +++ b/arrayfire/version.py @@ -0,0 +1,13 @@ +import os + +_MAJOR = "0" +_MINOR = "1" +# On main and in a nightly release the patch should be one ahead of the last +# released build. +_PATCH = "0" +# This is mainly for nightly builds which have the suffix ".dev$DATE". See +# https://semver.org/#is-v123-a-semantic-version for the semantics. +_SUFFIX = os.environ.get("AF_VERSION_SUFFIX", "") + +VERSION_SHORT = "{0}.{1}".format(_MAJOR, _MINOR) +VERSION = "{0}.{1}.{2}{3}".format(_MAJOR, _MINOR, _PATCH, _SUFFIX) diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b1210db --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +# Build requirements +setuptools +wheel + +# Development requirements +-e .[dev,test] diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..050e9ce --- /dev/null +++ b/setup.cfg @@ -0,0 +1,71 @@ +[metadata] +name = arrayfire +description = ArrayFire Python Wrapper +licence = BSD +long_description = file: README.md +long_description_content_type = text/markdown +author = ArrayFire +author_email = technical@arrayfire.com +url = http://arrayfire.com +classifiers = + Intended Audience :: Science/Research + Development Status :: 5 - Production/Stable + License :: OSI Approved :: BSD License + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.10 + Topic :: Scientific/Engineering + Topic :: Scientific/Engineering :: Artificial Intelligence + Topic :: Scientific/Engineering :: Information Analysis + Topic :: Scientific/Engineering :: Mathematics + Topic :: Software Development :: Libraries +keywords = + arrayfire parallel computing gpu cpu opencl + +[options] +packages = find: +install_requires = + scikit-build +python_requires = + >=3.10.0 + +[options.packages.find] +include = arrayfire +exclude = + examples + tests +install_requires = + numpy~=1.22.0 + +[options.extras_require] +dev = + autopep8~=1.6.0 + isort~=5.10.1 + flake8~=4.0.1 + flake8-quotes~=3.2.0 + mypy~=1.3.0 +test = + pytest~=7.1.2 + pytest-cov~=3.0.0 + pytest-isort~=3.0.0 + pytest-flake8~=1.1.1 + pytest-mypy~=0.3.0 + +[tool:isort] +line_length = 119 +multi_line_output = 4 + +[flake8] +exclude = venv +application-import-names = arrayfire +import-order-style = pep8 +inline-quotes = double +max-line-length = 119 + +[mypy] +exclude = venv +disallow_incomplete_defs = true +disallow_untyped_defs = true +ignore_missing_imports = true +show_error_codes = true +warn_return_any = true \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..13c7482 --- /dev/null +++ b/setup.py @@ -0,0 +1,11 @@ +from pathlib import Path + +from setuptools import setup + +VERSION: dict[str, str] = {} + + +with (Path().absolute() / "arrayfire" / "version.py").open("r") as version_file: + exec(version_file.read(), VERSION) + +setup(version=VERSION["VERSION"]) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100755 index 0000000..25acd56 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,51 @@ +import re + +import pytest + +from arrayfire.version import VERSION + +# Regex to check that the current version set in `arrayfire.version` adheres to +# PEP 440, as well as some of our own internal conventions, such as the `.dev` +# suffix being used only for nightly builds. +# 0.0.0rc0.post0.dev20200424 +VALID_VERSION_RE = re.compile( + r"^" + r"(0|[1-9]\d*)" # major + r"\.(0|[1-9]\d*)" # minor + r"\.(0|[1-9]\d*)" # patch + r"(rc(0|[1-9]\d*))?" # patch suffix + r"(\.post(0|[1-9]\d*))?" # [.postN] + r"(\.dev2020[0-9]{4})?" # [.devDATE] + r"$" +) + + +def is_valid(version: str) -> bool: + return VALID_VERSION_RE.match(version) is not None + + +@pytest.mark.parametrize( + "version, valid", + [ + # Valid versions: + ("1.0.0", True), + ("1.0.0rc3", True), + ("1.0.0.post0", True), + ("1.0.0.post1", True), + ("1.0.0rc3.post0", True), + ("1.0.0rc3.post0.dev20200424", True), + # Invalid versions: + ("1.0.0.rc3", False), + ("1.0.0rc01", False), + ("1.0.0rc3.dev2020424", False), + ], +) +def test_is_valid_helper(version: str, valid: bool) -> None: + assert is_valid(version) is valid + + +def test_version() -> None: + """ + Ensures current version is consistent with our conventions. + """ + assert is_valid(VERSION)