diff --git a/dask-gateway-server/LICENSE b/dask-gateway-server/LICENSE deleted file mode 120000 index ea5b6064..00000000 --- a/dask-gateway-server/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE \ No newline at end of file diff --git a/dask-gateway-server/LICENSE b/dask-gateway-server/LICENSE new file mode 100644 index 00000000..a95df9de --- /dev/null +++ b/dask-gateway-server/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2019, Jim Crist-Harif +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dask-gateway-server/MANIFEST.in b/dask-gateway-server/MANIFEST.in deleted file mode 100644 index 849752b5..00000000 --- a/dask-gateway-server/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -# MANIFEST.in declares final tweaks on what to include in a packaged source -# distribution (.tar.gz). -# -# MANIFEST.in reference documentation: -# https://packaging.python.org/en/latest/guides/using-manifest-in/ -# -include LICENSE - -# Include the Golang source code directory, but exclude any compiled binary -# built to a destination defined by PROXY_TGT_EXE in setup.py. -graft dask-gateway-proxy -exclude dask_gateway_server/proxy/dask-gateway-proxy diff --git a/dask-gateway-server/hatch_build.py b/dask-gateway-server/hatch_build.py new file mode 100644 index 00000000..8551eeb9 --- /dev/null +++ b/dask-gateway-server/hatch_build.py @@ -0,0 +1,250 @@ +""" +dask-gateway-server has Golang source code in ./dask-gateway-proxy that we want +to compile when installing or building a wheel. + +Based on the excellent code in: +- https://github.com/wandb/wandb/blob/77937418f17d0b93f96aaf53857f10bc27aec137/hatch_build.py +- https://github.com/wandb/wandb/blob/77937418f17d0b93f96aaf53857f10bc27aec137/core/hatch.py +""" + +import dataclasses +import os +import pathlib +import platform +import re +import shutil +import subprocess +import sysconfig +from collections.abc import Mapping +from typing import Any + +from hatchling.builders.hooks.plugin.interface import BuildHookInterface + +# Build options +_DASK_GATEWAY_SERVER__NO_PROXY = "DASK_GATEWAY_SERVER__NO_PROXY" + +SOURCE_DIR_PATH = pathlib.Path("dask-gateway-proxy") +TARGET_BINARY_PATH = pathlib.Path("dask_gateway_server", "proxy", "dask-gateway-proxy") + + +@dataclasses.dataclass(frozen=True) +class TargetPlatform: + goos: str + goarch: str + + +class CustomBuildHook(BuildHookInterface): + def initialize(self, version: str, build_data: dict[str, Any]) -> None: + if self.target_name == "wheel": + self._prepare_wheel(build_data) + + def clean(self, versions): + if os.path.exists(TARGET_BINARY_PATH): + os.remove(TARGET_BINARY_PATH) + + def _prepare_wheel(self, build_data: dict[str, Any]) -> None: + artifacts: list[str] = build_data["artifacts"] + + if self._is_platform_wheel(): + build_data["tag"] = f"py3-none-{self._get_platform_tag()}" + else: + build_data["tag"] = "py3-none-any" + + if self._include_dask_gateway_proxy(): + artifacts.extend(self._build_dask_gateway_proxy()) + + def _get_platform_tag(self) -> str: + """Returns the platform tag for the current platform.""" + # Replace dots, spaces and dashes with underscores following + # https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/#platform-tag + platform_tag = re.sub("[-. ]", "_", sysconfig.get_platform()) + + # On macOS versions >=11, pip expects the minor version to be 0: + # https://github.com/pypa/packaging/issues/435 + # + # You can see the list of tags that pip would support on your machine + # using `pip debug --verbose`. On my macOS, get_platform() returns + # 14.1, but `pip debug --verbose` reports only these py3 tags with 14: + # + # * py3-none-macosx_14_0_arm64 + # * py3-none-macosx_14_0_universal2 + # + # We do this remapping here because otherwise, it's possible for `pip wheel` + # to successfully produce a wheel that you then cannot `pip install` on the + # same machine. + macos_match = re.fullmatch(r"macosx_(\d+_\d+)_(\w+)", platform_tag) + if macos_match: + major, _ = macos_match.group(1).split("_") + if int(major) >= 11: + arch = macos_match.group(2) + platform_tag = f"macosx_{major}_0_{arch}" + + return platform_tag + + def _include_dask_gateway_proxy(self) -> bool: + """Whether the wheel bundles with the dask-gateway-proxy Go binary.""" + return not _get_env_bool(_DASK_GATEWAY_SERVER__NO_PROXY, False) + + def _is_platform_wheel(self) -> bool: + """Whether the wheel will be platform-specific.""" + return self._include_dask_gateway_proxy() + + def _build_dask_gateway_proxy(self) -> list[str]: + plat = self._target_platform() + + self.app.display_waiting( + f"Building dask-gateway-proxy Go binary ({plat.goos}-{plat.goarch})..." + ) + _go_build_dask_gateway_proxy( + go_binary=self._get_and_require_go_binary(), + output_path=TARGET_BINARY_PATH, + target_system=plat.goos, + target_arch=plat.goarch, + ) + + # NOTE: as_posix() is used intentionally. Hatch expects forward slashes + # even on Windows. + return [TARGET_BINARY_PATH.as_posix()] + + def _get_and_require_go_binary(self) -> pathlib.Path: + go = shutil.which("go") + + if not go: + self.app.abort( + "Did not find the 'go' binary. You need Go to build dask-gateway-proxy" + " from source. See https://go.dev/doc/install.", + ) + raise AssertionError("unreachable") + + return pathlib.Path(go) + + def _target_platform(self) -> "TargetPlatform": + """Returns the platform we're building for (for cross-compilation).""" + if os.environ.get("GOOS") and os.environ.get("GOARCH"): + return TargetPlatform( + goos=os.environ.get("GOOS"), + goarch=os.environ.get("GOARCH"), + ) + + # Checking sysconfig.get_platform() is the "standard" way of getting the + # target platform in Python cross-compilation. Build tools like + # cibuildwheel control its output by setting the undocumented + # _PYTHON_HOST_PLATFORM environment variable which is also a good way + # of manually testing this function. + plat = sysconfig.get_platform() + match = re.match( + r"(win|linux|macosx-.+)-(aarch64|arm64|x86_64|amd64)", + plat, + ) + if match: + if match.group(1).startswith("macosx"): + goos = "darwin" + elif match.group(1) == "win": + goos = "windows" + else: + goos = match.group(1) + + goarch = _to_goarch(match.group(2)) + + return TargetPlatform( + goos=goos, + goarch=goarch, + ) + + self.app.display_warning( + f"Failed to parse sysconfig.get_platform() ({plat}); disabling" + " cross-compilation.", + ) + + host_os = platform.system().lower() + if host_os in ("windows", "darwin", "linux"): + goos = host_os + else: + goos = "" + + goarch = _to_goarch(platform.machine().lower()) + + return TargetPlatform( + goos=goos, + goarch=goarch, + ) + + +def _get_env_bool(name: str, default: bool) -> bool: + """Returns the value of a boolean environment variable.""" + value = os.getenv(name) + + if value is None: + return default + elif value.lower() in ("1", "true"): + return True + elif value.lower() in ("0", "false"): + return False + else: + raise ValueError( + f"Environment variable '{name}' has invalid value '{value}'" + " expected one of {1,true,0,false}." + ) + + +def _to_goarch(arch: str) -> str: + """Returns a valid GOARCH value or the empty string.""" + return { + # amd64 synonyms + "amd64": "amd64", + "x86_64": "amd64", + # arm64 synonyms + "arm64": "arm64", + "aarch64": "arm64", + }.get(arch, "") + + +def _go_build_dask_gateway_proxy( + go_binary: pathlib.Path, + output_path: pathlib.PurePath, + target_system, + target_arch, +) -> None: + """Builds the dask-gateway-proxy Go module. + + Args: + go_binary: Path to the Go binary, which must exist. + output_path: The path where to output the binary, relative to the + workspace root. + target_system: The target operating system (GOOS) or an empty string + to use the current OS. + target_arch: The target architecture (GOARCH) or an empty string + to use the current architecture. + """ + cmd = [ + str(go_binary), + "build", + f"-ldflags={_go_linker_flags()}", + f"-o={str('..' / output_path)}", + str(pathlib.Path("cmd", "dask-gateway-proxy", "main.go")), + ] + cwd = str(SOURCE_DIR_PATH) + env = _go_env( + target_system=target_system, + target_arch=target_arch, + ) + + subprocess.check_call(cmd, cwd=cwd, env=env) + + +def _go_linker_flags() -> str: + """Returns linker flags for the Go binary as a string.""" + flags = [ + "-s", # Omit the symbol table and debug info. + ] + return " ".join(flags) + + +def _go_env(target_system: str, target_arch: str) -> Mapping[str, str]: + env = os.environ.copy() + + env["GOOS"] = target_system + env["GOARCH"] = target_arch + env["CGO_ENABLED"] = "0" + + return env diff --git a/dask-gateway-server/pyproject.toml b/dask-gateway-server/pyproject.toml index 9cc879ac..cb19e435 100644 --- a/dask-gateway-server/pyproject.toml +++ b/dask-gateway-server/pyproject.toml @@ -1,28 +1,76 @@ +# build-system +# - ref: https://peps.python.org/pep-0517/ +# [build-system] -requires = [ - # FIXME: dask-gateway-server's editable install is broken with setuptools - # 64+ that introduced the "editable_wheel" command to replace the - # "develop" command, and that doesn't respect package_data config. We - # rely on that to get our golang built proxy accessible currently! - # - # At the same time, setuptools 63 and older doesn't support Python - # 3.12, so we end up with a broken editable install in Python 3.12 - # until this is resolved. - # - # Message when using "setuptools>=64" during "pip install --editable .": - # - # Editable install will be performed using a meta path finder. - # - # Options like `package-data`, `include/exclude-package-data` or - # `packages.find.exclude/include` may have no effect. - # - # The problematic result is that we end up without a golang binary in - # dask_gateway_server/proxy/dask-gateway-proxy. - # - # This is tracked in https://github.com/dask/dask-gateway/issues/740 - # - 'setuptools==63.* ; python_version < "3.12"', - 'setuptools==69.* ; python_version >= "3.12"', - "wheel", +requires = ["hatchling"] +build-backend = "hatchling.build" + +# project +# - ref 1: https://peps.python.org/pep-0621/ +# - ref 2: https://hatch.pypa.io/latest/config/metadata/#project-metadata +# +[project] +name = "dask-gateway-server" +version = "2024.1.0" +description = "A multi-tenant server for securely deploying and managing multiple Dask clusters." +readme = "README.rst" +requires-python = ">=3.10" +license = {file = "LICENSE"} +keywords = ["dask", "hadoop", "kubernetes", "HPC", "distributed", "cluster"] +authors = [ + {name = "Jim Crist-Harif", email = "jcristharif@gmail.com"}, +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: BSD License", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Intended Audience :: System Administrators", + "Topic :: Scientific/Engineering", + "Topic :: System :: Distributed Computing", + "Topic :: System :: Systems Administration", + "Programming Language :: Python :: 3", +] +dependencies = [ + "aiohttp>=3.9.0", + "async-timeout ; python_version < '3.11'", + "colorlog", + "cryptography", + "traitlets>=5.2.2.post1", +] + +[project.optional-dependencies] +kerberos = [ + # pykerberos is tricky to install and requires a system package to + # successfully compile some C code, on ubuntu this is libkrb5-dev. + "pykerberos", +] +jobqueue = ["sqlalchemy>=2.0.0"] +local = ["sqlalchemy>=2.0.0"] +yarn = ["sqlalchemy>=2.0.0", "skein >= 0.7.3"] +kubernetes = ["kubernetes_asyncio"] +all_backends = ["sqlalchemy>=2.0.0", "skein >= 0.7.3", "kubernetes_asyncio"] + +[project.urls] +Documentation = "https://gateway.dask.org/" +Source = "https://github.com/dask/dask-gateway/" +Issues = "https://github.com/dask/dask-gateway/issues" + +[project.scripts] +dask-gateway-server = "dask_gateway_server.app:main" +dask-gateway-jobqueue-launcher = "dask_gateway_server.backends.jobqueue.launcher:main" + + +# Refs: +# - https://hatch.pypa.io/latest/plugins/build-hook/custom/#pyprojecttoml +# - https://hatch.pypa.io/1.3/plugins/build-hook/reference/#hatchling.builders.hooks.plugin.interface.BuildHookInterface.clean +# - https://github.com/ofek/hatch-mypyc/blob/master/hatch_mypyc/plugin.py +# +[tool.hatch.build.hooks.custom] +path = "hatch_build.py" + +[tool.hatch.build] +include = [ + "**/*.py", + "dask-gateway-proxy/**", ] -build-backend = "setuptools.build_meta" diff --git a/dask-gateway-server/requirements.txt b/dask-gateway-server/requirements.txt deleted file mode 100644 index fa83ea21..00000000 --- a/dask-gateway-server/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# These are dependencies for installing the dask-gateway-server package. -# -aiohttp>=3.9.0 -async-timeout ; python_version < "3.11" -colorlog -cryptography -traitlets>=5.2.2.post1 diff --git a/dask-gateway-server/setup.py b/dask-gateway-server/setup.py deleted file mode 100644 index 6d158801..00000000 --- a/dask-gateway-server/setup.py +++ /dev/null @@ -1,269 +0,0 @@ -""" -dask-gateway-server has Golang source code in ./dask-gateway-proxy that we want -to compile as part of installing this Package and building a source distribution -or wheels. There is also metadata of a wheel that we would like to set. Because -of this, this setup.py file includes some related complexity. - -Relevant reference documentation: -- https://setuptools.pypa.io/en/latest/userguide/extension.html#adding-commands -""" - -import errno -import os -import subprocess -import sys - -# distutils is deprecated but we need to keep using these imports, see -# https://github.com/pypa/setuptools/issues/2928 -from distutils.command.build import build as _build -from distutils.command.clean import clean as _clean - -from setuptools import Command, find_packages, setup -from setuptools.command.develop import develop as _develop -from setuptools.command.install import install as _install -from wheel.bdist_wheel import bdist_wheel as _bdist_wheel - -ROOT_DIR = os.path.abspath(os.path.dirname(__file__)) -PROXY_SRC_DIR = os.path.join(ROOT_DIR, "dask-gateway-proxy") -PROXY_TGT_DIR = os.path.join(ROOT_DIR, "dask_gateway_server", "proxy") -PROXY_TGT_EXE = os.path.join(PROXY_TGT_DIR, "dask-gateway-proxy") - - -class build_proxy(Command): - """ - A command the compile the golang code in ./dask-gateway-proxy and copy the - executable binary to dask_gateway_server/proxy/dask-gateway-proxy to be - picked up via package_data. - - setuptools.Command derived classes are required to implement - initialize_options, finalize_options, and run. - """ - - description = "build go artifact" - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - self.mkpath(PROXY_TGT_DIR) - try: - code = subprocess.call( - ["go", "build", "-o", PROXY_TGT_EXE, "./cmd/dask-gateway-proxy"], - cwd=PROXY_SRC_DIR, - ) - except OSError as exc: - if exc.errno == errno.ENOENT: - self.warn( - "Building dask-gateway-server requires a go compiler, " - "which wasn't found in your environment. Please install " - "go using a package manager (e.g. apt, brew, conda, etc...), " - "or download from https://go.dev/dl/." - ) - sys.exit(1) - raise - if code: - sys.exit(code) - - -class build_proxy_mixin: - """ - This mixin class helps us ensure that we build the dask-gateway-proxy - executable binary no matter if we run the: install, build, develop, or - bdist_wheel command. - """ - - def run(self): - if ( - not os.environ.get("DASK_GATEWAY_SERVER__NO_PROXY") - and not getattr(self, "uninstall", False) - and not os.path.exists(PROXY_TGT_EXE) - ): - self.run_command("build_proxy") - super().run() - - -class build(build_proxy_mixin, _build): - pass - - -class install(build_proxy_mixin, _install): - pass - - -class develop(build_proxy_mixin, _develop): - pass - - -class bdist_wheel(build_proxy_mixin, _bdist_wheel): - """ - When we build wheels, they are without this override named - "-py3-none-any.whl" which is incorrect as we have a platform - dependency. - - By overriding the `root_is_pure` option and the `get_tag` we can declare - a dependency to the Golang compiled executable binary. - - This is based on https://stackoverflow.com/a/45150383/2220152. - """ - - def finalize_options(self): - super().finalize_options() - # Cleanup binaries ahead of time to avoid packaging an existing - # binary with the wheel that shouldn't be packaged. - if os.path.exists(PROXY_TGT_EXE): - os.remove(PROXY_TGT_EXE) - - if os.environ.get("DASK_GATEWAY_SERVER__NO_PROXY"): - self.root_is_pure = True - else: - self.root_is_pure = False - - def get_tag(self): - python, abi, plat = super().get_tag() - python, abi = "py3", "none" - - if os.environ.get("DASK_GATEWAY_SERVER__NO_PROXY"): - return python, abi, "any" - - # If GOOS or GOARCH are set, we will probably be cross compiling. - # Below we act intelligently based on a few combinations of GOOS and - # GOARCH to provide a platform tag that is accepted by PyPI. - # - # PyPI restricts us to using the following platform tags: - # https://github.com/pypa/warehouse/blob/82815b06d9f98deed5f205c66e054de59d22a10d/warehouse/forklift/legacy.py#L108-L180 - # - # For reference, GitHub Actions available operating systems: - # https://github.com/actions/virtual-environments#available-environments - # - go_plat = os.environ.get("GOOS", "") + "_" + os.environ.get("GOARCH", "") - go_plat_to_pypi_plat_mapping = { - "linux_amd64": "manylinux_2_17_x86_64", - "linux_arm64": "manylinux_2_17_aarch64", - "darwin_amd64": "macosx_10_15_x86_64", - "darwin_arm64": "macosx_11_0_arm64", - } - if go_plat in go_plat_to_pypi_plat_mapping: - plat = go_plat_to_pypi_plat_mapping[go_plat] - - return python, abi, plat - - -class clean(_clean): - def run(self): - super().run() - if self.all and os.path.exists(PROXY_TGT_EXE): - os.remove(PROXY_TGT_EXE) - - -# cmdclass describes commands we can run with "python setup.py ". We -# have overridden several command classes by mixing in a common capability of -# compiling the golang executable binary. -# -# It seems that only by overriding multiple command classes we can ensure we -# manage to compile the Golang executable binary before its needed. Below are -# examples of end user commands that are impacted by our changes to cmdclass. -# -# python setup.py [bdist_wheel|build|install|develop|clean] -# python -m pip install [--editable] . -# python -m build --wheel . -# -cmdclass = { - "bdist_wheel": bdist_wheel, - "build": build, - "build_proxy": build_proxy, - "install": install, - "clean": clean, - "develop": develop, -} - -if os.environ.get("DASK_GATEWAY_SERVER__NO_PROXY"): - package_data = {} -else: - # FIXME: Does it make sense to put the binary next to the source code - # (proxy/dask-gateway-proxy)? If we build a wheel now we get a folder in - # the wheel called purelib that includes this and it seems contradictory. - # - # An action point to resolve this would be to investigate how other - # projects have bundled compiled binaries. - # - package_data = {"dask_gateway_server": ["proxy/dask-gateway-proxy"]} - -# determine version from _version.py -ns = {} -with open(os.path.join(ROOT_DIR, "dask_gateway_server", "_version.py")) as f: - exec(f.read(), {}, ns) - VERSION = ns["__version__"] - -with open("requirements.txt") as f: - install_requires = [l for l in f.readlines() if not l.startswith("#")] - -extras_require = { - # pykerberos is tricky to install and requires a system package to - # successfully compile some C code, on ubuntu this is libkrb5-dev. - "kerberos": ["pykerberos"], - "jobqueue": ["sqlalchemy>=2.0.0"], - "local": ["sqlalchemy>=2.0.0"], - "yarn": ["sqlalchemy>=2.0.0", "skein >= 0.7.3"], - "kubernetes": ["kubernetes_asyncio"], - "all_backends": [ - "sqlalchemy>=2.0.0", - "skein >= 0.7.3", - "kubernetes_asyncio", - ], -} - - -# setup's keyword reference: -# https://setuptools.pypa.io/en/latest/references/keywords.html -# -setup( - name="dask-gateway-server", - version=VERSION, - cmdclass=cmdclass, - maintainer="Jim Crist-Harif", - maintainer_email="jcristharif@gmail.com", - license="BSD", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: BSD License", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Intended Audience :: System Administrators", - "Topic :: Scientific/Engineering", - "Topic :: System :: Distributed Computing", - "Topic :: System :: Systems Administration", - "Programming Language :: Python :: 3", - ], - keywords="dask hadoop kubernetes HPC distributed cluster", - description=( - "A multi-tenant server for securely deploying and managing " - "multiple Dask clusters." - ), - long_description=open("README.rst").read(), - long_description_content_type="text/x-rst", - url="https://gateway.dask.org/", - project_urls={ - "Documentation": "https://gateway.dask.org/", - "Source": "https://github.com/dask/dask-gateway/", - "Issue Tracker": "https://github.com/dask/dask-gateway/issues", - }, - packages=find_packages(), - package_data=package_data, - install_requires=install_requires, - extras_require=extras_require, - python_requires=">=3.10", - entry_points={ - "console_scripts": [ - "dask-gateway-server = dask_gateway_server.app:main", - ( - "dask-gateway-jobqueue-launcher = " - "dask_gateway_server.backends.jobqueue.launcher:main" - ), - ] - }, - zip_safe=False, -) diff --git a/dask-gateway/LICENSE b/dask-gateway/LICENSE deleted file mode 120000 index ea5b6064..00000000 --- a/dask-gateway/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../LICENSE \ No newline at end of file diff --git a/dask-gateway/LICENSE b/dask-gateway/LICENSE new file mode 100644 index 00000000..a95df9de --- /dev/null +++ b/dask-gateway/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2019, Jim Crist-Harif +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dask-gateway/MANIFEST.in b/dask-gateway/MANIFEST.in deleted file mode 100644 index d655d021..00000000 --- a/dask-gateway/MANIFEST.in +++ /dev/null @@ -1,6 +0,0 @@ -recursive-include dask_gateway *.py -recursive-include dask_gateway *.yaml - -include setup.py -include README.rst -include LICENSE diff --git a/dask-gateway/pyproject.toml b/dask-gateway/pyproject.toml new file mode 100644 index 00000000..88d4cab4 --- /dev/null +++ b/dask-gateway/pyproject.toml @@ -0,0 +1,57 @@ +# build-system +# - ref: https://peps.python.org/pep-0517/ +# +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +# project +# - ref 1: https://peps.python.org/pep-0621/ +# - ref 2: https://hatch.pypa.io/latest/config/metadata/#project-metadata +# +[project] +name = "dask-gateway" +version = "2024.1.0" +description = "A client library for interacting with a dask-gateway server" +readme = "README.rst" +requires-python = ">=3.10" +license = {file = "LICENSE"} +keywords = ["dask", "hadoop", "kubernetes", "HPC", "distributed", "cluster"] +authors = [ + {name = "Jim Crist-Harif", email = "jcristharif@gmail.com"}, +] + +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: BSD License", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "Topic :: System :: Distributed Computing", + "Programming Language :: Python :: 3", +] +dependencies = [ + "aiohttp", + "click>=8.1.3", + "dask>=2022.4.0", + "distributed>=2022.4.0", + "pyyaml", + "tornado", +] + +[project.optional-dependencies] +kerberos = [ + 'pykerberos;platform_system!="Windows"', + 'winkerberos;platform_system=="Windows"', +] + +[project.urls] +Documentation = "https://gateway.dask.org/" +Source = "https://github.com/dask/dask-gateway/" +Issues = "https://github.com/dask/dask-gateway/issues" + +[tool.hatch.build] +include = [ + "**/*.py", + "**/*.yaml", +] diff --git a/dask-gateway/requirements.txt b/dask-gateway/requirements.txt deleted file mode 100644 index d517ab86..00000000 --- a/dask-gateway/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# These are dependencies for installing the dask-gateway package. -# -aiohttp -click>=8.1.3 -dask>=2022.4.0 -distributed>=2022.4.0 -pyyaml -tornado diff --git a/dask-gateway/setup.py b/dask-gateway/setup.py deleted file mode 100644 index c5092bbb..00000000 --- a/dask-gateway/setup.py +++ /dev/null @@ -1,53 +0,0 @@ -import os - -from setuptools import find_packages, setup - -# determine version from _version.py -ns = {} -here = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(here, "dask_gateway", "_version.py")) as f: - exec(f.read(), {}, ns) - VERSION = ns["__version__"] - -with open("requirements.txt") as f: - install_requires = [l for l in f.readlines() if not l.startswith("#")] - -extras_require = { - "kerberos": [ - 'pykerberos;platform_system!="Windows"', - 'winkerberos;platform_system=="Windows"', - ], -} - -setup( - name="dask-gateway", - version=VERSION, - maintainer="Jim Crist-Harif", - maintainer_email="jcristharif@gmail.com", - license="BSD", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: BSD License", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering", - "Topic :: System :: Distributed Computing", - "Programming Language :: Python :: 3", - ], - keywords="dask hadoop kubernetes HPC distributed cluster", - description="A client library for interacting with a dask-gateway server", - long_description=open("README.rst").read(), - long_description_content_type="text/x-rst", - url="https://gateway.dask.org/", - project_urls={ - "Documentation": "https://gateway.dask.org/", - "Source": "https://github.com/dask/dask-gateway/", - "Issue Tracker": "https://github.com/dask/dask-gateway/issues", - }, - packages=find_packages(), - package_data={"dask_gateway": ["*.yaml"]}, - install_requires=install_requires, - extras_require=extras_require, - python_requires=">=3.10", - zip_safe=False, -) diff --git a/docs/requirements.txt b/docs/requirements.txt index 976d21e3..eb3741b4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -34,6 +34,4 @@ sphinx-autobuild # autodoc-traits --editable="./dask-gateway" -# FIXME: See dask-gateway-server's pyproject.toml for more info why this isn't -# installed with --editable. -./dask-gateway-server[all_backends] +--editable="./dask-gateway-server[all_backends]" diff --git a/pyproject.toml b/pyproject.toml index f78eab9e..2b1f4945 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,10 +71,18 @@ regex = ''' message_template = "Release {new_version}" tag_template = "{new_version}" +[[tool.tbump.file]] +src = "dask-gateway/pyproject.toml" +search = 'version = "{current_version}"' + [[tool.tbump.file]] src = "dask-gateway/dask_gateway/_version.py" search = '__version__ = "{current_version}"' +[[tool.tbump.file]] +src = "dask-gateway-server/pyproject.toml" +search = 'version = "{current_version}"' + [[tool.tbump.file]] src = "dask-gateway-server/dask_gateway_server/_version.py" search = '__version__ = "{current_version}"' diff --git a/tests/requirements.txt b/tests/requirements.txt index 9f1d1e45..437d516b 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -26,9 +26,7 @@ pytest-timeout # dask-gateway and dask-gateway-server and all their dependencies are assumed to # be installed. --editable="./dask-gateway" -# FIXME: See dask-gateway-server's pyproject.toml for more info why this isn't -# installed with --editable. -./dask-gateway-server[all_backends] +--editable="./dask-gateway-server[all_backends]" # ipython and ipywidget is optional integrations allowing for fancy rendering of # end user provided configuration options. Tests in test_options.py will be