Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions continuous_integration/environment-3.7.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies:
- dask # overridden by git tip below
- filesystem-spec
- h5py
- importlib_metadata # Only needed here
- ipykernel
- ipywidgets
- jinja2
Expand Down
13 changes: 6 additions & 7 deletions distributed/tests/test_versions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import re
import sys

import msgpack
import pytest
import tornado

Expand Down Expand Up @@ -145,17 +146,15 @@ def test_python_version():
def test_version_custom_pkgs():
out = get_versions(
[
# Use custom function
("distributed", lambda mod: "123"),
# Use version_of_package
"notexist",
("pytest", None), # has __version__
"tornado", # has version
"math", # has nothing
"pytest",
"tornado",
"msgpack",
"math",
]
)["packages"]
assert out["distributed"] == "123"
assert out["notexist"] is None
assert out["pytest"] == pytest.__version__
assert out["tornado"] == tornado.version
assert out["msgpack"] == ".".join(str(v) for v in msgpack.version)
assert out["math"] is None
77 changes: 26 additions & 51 deletions distributed/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,34 @@

from __future__ import annotations

import importlib
import importlib.metadata
import os
Comment thread
crusaderky marked this conversation as resolved.
import platform
import struct
import sys
from collections.abc import Callable, Iterable
from collections.abc import Iterable
from itertools import chain
from types import ModuleType
from typing import Any

required_packages = [
("dask", lambda p: p.__version__),
("distributed", lambda p: p.__version__),
("msgpack", lambda p: ".".join([str(v) for v in p.version])),
("cloudpickle", lambda p: p.__version__),
("tornado", lambda p: p.version),
("toolz", lambda p: p.__version__),
required_packages: list[str] = [
Comment thread
gjoseph92 marked this conversation as resolved.
Outdated
"dask",
"distributed",
"msgpack",
"cloudpickle",
"tornado",
"toolz",
]

optional_packages = [
("numpy", lambda p: p.__version__),
("pandas", lambda p: p.__version__),
("lz4", lambda p: p.__version__),
("blosc", lambda p: p.__version__),
optional_packages: list[str] = [
"numpy",
"pandas",
"lz4",
"blosc",
]


# only these scheduler packages will be checked for version mismatch
scheduler_relevant_packages = {pkg for pkg, _ in required_packages} | {"lz4", "blosc"}
scheduler_relevant_packages = set(required_packages) | {"lz4", "blosc"}


# notes to be displayed for mismatch packages
Expand All @@ -39,18 +38,18 @@
}


def get_versions(
packages: Iterable[str | tuple[str, Callable[[ModuleType], str | None]]]
| None = None
) -> dict[str, dict[str, Any]]:
def get_versions(packages: Iterable[str] | None = None) -> dict[str, dict[str, Any]]:
Comment thread
gjoseph92 marked this conversation as resolved.
Outdated
"""Return basic information on our software installation, and our installed versions
of packages
"""
return {
"host": get_system_info(),
"packages": get_package_info(
chain(required_packages, optional_packages, packages or [])
),
"packages": {
"python": ".".join(map(str, sys.version_info)),
**get_package_info(
chain(required_packages, optional_packages, packages or [])
Comment thread
gjoseph92 marked this conversation as resolved.
Outdated
),
},
}


Expand All @@ -69,37 +68,13 @@ def get_system_info() -> dict[str, Any]:
}


def version_of_package(pkg: ModuleType) -> str | None:
"""Try a variety of common ways to get the version of a package"""
from contextlib import suppress

with suppress(AttributeError):
return pkg.__version__ # type: ignore
with suppress(AttributeError):
return str(pkg.version) # type: ignore
with suppress(AttributeError):
return ".".join(map(str, pkg.version_info)) # type: ignore
return None


def get_package_info(
pkgs: Iterable[str | tuple[str, Callable[[ModuleType], str | None]]]
) -> dict[str, str | None]:
def get_package_info(pkgs: Iterable[str]) -> dict[str, str | None]:
"""get package versions for the passed required & optional packages"""

pversions: dict[str, str | None] = {"python": ".".join(map(str, sys.version_info))}
for pkg in pkgs:
if isinstance(pkg, (tuple, list)):
modname, ver_f = pkg
if ver_f is None:
ver_f = version_of_package
else:
modname = pkg
ver_f = version_of_package

pversions: dict[str, str | None] = {}
for modname in pkgs:
try:
mod = importlib.import_module(modname)
pversions[modname] = ver_f(mod)
pversions[modname] = importlib.metadata.version(modname)
except Exception:
pversions[modname] = None

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
click >= 6.6
cloudpickle >= 1.5.0
dask == 2022.01.0
importlib_metadata >= 1.4;python_version<'3.8'
jinja2
msgpack >= 0.6.0
packaging >= 20.0
Expand Down