Skip to content

Commit 7a6eeeb

Browse files
authored
feat(package): expose swarms.__version__ (kyegomez#2129)
`import swarms; swarms.__version__` raised AttributeError. The package defined no `__version__` and no module `__getattr__`, so the attribute every Python package is expected to carry simply was not there. This is not only a docs problem. scripts/docker/test_docker.py reads swarms.__version__ twice as its smoke test, catches the AttributeError in a bare `except Exception`, and reports "Tests failed! Please check the Docker image" on a perfectly good install. The command documented in scripts/docker/DOCKER.md fails the same way. The version is read from the installed distribution's metadata rather than duplicated as a literal, so it cannot drift from the version in pyproject.toml the way a hand-maintained string does. Resolution is deferred to first access through a module `__getattr__`, then cached in globals(). importlib.metadata.version() scans dist-info and costs ~0.44ms, which is not worth adding to every `import swarms` for an attribute most programs never read. A `__dir__` is included so the name is still discoverable before anything has touched it, which is what kyegomez#196 originally asked for. A source checkout with no installed distribution has no metadata to read and reports "unknown" rather than raising, so the attribute is safe to reference unconditionally. Tests: 8 in tests/test___init__.py, which was an empty file. 7 fail against master.
1 parent 399b743 commit 7a6eeeb

2 files changed

Lines changed: 110 additions & 0 deletions

File tree

swarms/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,36 @@
1414
from swarms.telemetry import * # noqa: E402, F403
1515
from swarms.tools import * # noqa: E402, F403
1616
from swarms.utils import * # noqa: E402, F403
17+
18+
19+
def __getattr__(name: str) -> str:
20+
"""Resolve ``swarms.__version__`` on first access.
21+
22+
The version comes from the installed distribution's metadata rather
23+
than a literal here, so it cannot drift from ``pyproject.toml``.
24+
Resolving it lazily keeps the dist-info scan off the import path for
25+
the majority of programs, which never read it.
26+
"""
27+
if name == "__version__":
28+
from importlib.metadata import (
29+
PackageNotFoundError,
30+
version,
31+
)
32+
33+
try:
34+
resolved = version("swarms")
35+
except PackageNotFoundError:
36+
# A source checkout with no installed distribution.
37+
resolved = "unknown"
38+
39+
globals()["__version__"] = resolved
40+
return resolved
41+
42+
raise AttributeError(
43+
f"module {__name__!r} has no attribute {name!r}"
44+
)
45+
46+
47+
def __dir__() -> list:
48+
"""Advertise ``__version__`` before anything has accessed it."""
49+
return sorted(set(globals()) | {"__version__"})

tests/test___init__.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import re
2+
import subprocess
3+
import sys
4+
from importlib.metadata import PackageNotFoundError
5+
6+
import pytest
7+
8+
import swarms
9+
10+
11+
def test_version_attribute_exists():
12+
assert isinstance(swarms.__version__, str)
13+
assert swarms.__version__
14+
15+
16+
def test_version_matches_installed_distribution():
17+
from importlib.metadata import version
18+
19+
assert swarms.__version__ == version("swarms")
20+
21+
22+
def test_version_is_pep440_shaped():
23+
assert re.match(
24+
r"^\d+\.\d+", swarms.__version__
25+
), f"expected a numeric version, got {swarms.__version__!r}"
26+
27+
28+
def test_hasattr_reports_true():
29+
assert hasattr(swarms, "__version__")
30+
31+
32+
def test_version_is_advertised_by_dir_before_access():
33+
"""dir() lists it even in a process that has never read it."""
34+
result = subprocess.run(
35+
[
36+
sys.executable,
37+
"-c",
38+
"import swarms; print('__version__' in dir(swarms))",
39+
],
40+
capture_output=True,
41+
text=True,
42+
)
43+
assert result.stdout.strip().endswith("True"), result.stderr
44+
45+
46+
def test_unknown_attribute_still_raises_attribute_error():
47+
with pytest.raises(AttributeError) as excinfo:
48+
swarms.definitely_not_a_real_attribute
49+
50+
assert "definitely_not_a_real_attribute" in str(excinfo.value)
51+
52+
53+
def test_version_is_cached_after_first_access():
54+
"""The second read comes from globals(), not a fresh metadata scan."""
55+
swarms.__version__
56+
assert "__version__" in vars(swarms)
57+
58+
59+
def test_falls_back_when_distribution_is_absent(monkeypatch):
60+
"""A source checkout with no installed dist reports 'unknown'."""
61+
import importlib.metadata as metadata
62+
63+
monkeypatch.delitem(vars(swarms), "__version__", raising=False)
64+
65+
def _raise(name):
66+
raise PackageNotFoundError(name)
67+
68+
monkeypatch.setattr(metadata, "version", _raise)
69+
70+
assert swarms.__getattr__("__version__") == "unknown"
71+
72+
monkeypatch.undo()
73+
vars(swarms).pop("__version__", None)
74+
75+
76+
if __name__ == "__main__":
77+
pytest.main([__file__])

0 commit comments

Comments
 (0)