Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed
- `__version__` is now derived from installed package metadata via
`importlib.metadata` instead of a hardcoded string, so it stays in sync
with `pyproject.toml` automatically.
- `Operating System` classifier widened from `POSIX :: Linux` to `POSIX`
to match the documented support range (Linux, macOS, WSL).
- Added `Changelog` URL to `[project.urls]` (linked from PyPI sidebar).

## [0.1.0a0] — 2026-06-11

Initial alpha release.

### Added
- `AnsibleHost`, `AnsibleHosts`, `AnsibleLocalhost` classes for in-process
Ansible module execution with structured results.
- Dynamic dispatch: any Ansible module is callable as a method
(e.g. `host.ping()`, `host.command("uname -a")`).
- Batch execution via context manager (`with host:`) and via explicit
`load_module` / `run_loaded_modules`.
- Container protocol on `AnsibleHosts` (`len`, `[]` by int or hostname,
iteration).
- Per-host failure aggregation via `task_directives={"ignore_errors": True}`.
- Verbosity-controlled debug logging via the `ansible_host` logger and the
`ANSIBLE_HOST_VERBOSITY` environment variable.
- Inline `_JsonResultsCallback` for result collection without a separate
plugin file.
- Tier-1 integration test suite (30 tests) using Ansible's `local`
connection — no SSH or Docker required.
- Tier-A logging/verbosity tests guarding `display.verbosity` save/restore
and the verbosity ladder contract.

### Supported
- Python 3.10, 3.11, 3.12, 3.13
- ansible-core 2.16, 2.17, 2.18, 2.19, 2.20, 2.21
- POSIX systems (Linux, macOS, WSL); not supported on native Windows.

[Unreleased]: https://github.com/wangxin/ansible-host/compare/v0.1.0a0...HEAD
[0.1.0a0]: https://github.com/wangxin/ansible-host/releases/tag/v0.1.0a0
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: Apache Software License",
"Operating System :: POSIX :: Linux",
"Operating System :: POSIX",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -47,6 +47,7 @@ dev = [
Homepage = "https://github.com/wangxin/ansible-host"
Source = "https://github.com/wangxin/ansible-host"
Issues = "https://github.com/wangxin/ansible-host/issues"
Changelog = "https://github.com/wangxin/ansible-host/blob/main/CHANGELOG.md"

[tool.hatch.build.targets.wheel]
packages = ["src/ansible_host"]
Expand All @@ -56,6 +57,7 @@ include = [
"src/ansible_host",
"tests",
"README.md",
"CHANGELOG.md",
"LICENSE",
"pyproject.toml",
]
Expand Down
11 changes: 9 additions & 2 deletions src/ansible_host/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import json
import logging
import os
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _pkg_version
from typing import Any

import ansible
Expand All @@ -39,6 +41,13 @@
display = Display()
init_plugin_loader()

try:
__version__ = _pkg_version("ansible-host")
except PackageNotFoundError:
# Source checkout without installed metadata (e.g., running from a tarball
# without ``pip install -e .``). Falls back to an inert marker.
__version__ = "0.0.0+unknown"

# Logger for the ansible-host library. Users can configure verbosity by
# attaching handlers to this logger (logging.getLogger("ansible_host")).
logger = logging.getLogger("ansible_host")
Expand Down Expand Up @@ -1091,8 +1100,6 @@ def __repr__(self) -> str:
return f"AnsibleLocalhost(inventory={inv_str}, connection='local')"


__version__ = "0.1.0a0"

__all__ = [
"AnsibleHost",
"AnsibleHosts",
Expand Down
8 changes: 8 additions & 0 deletions tests/test_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ def test_version_present():

assert isinstance(ansible_host.__version__, str)
assert ansible_host.__version__
# Must match installed package metadata (i.e., pyproject.toml [project].version),
# not be the inert fallback. Catches a stale hardcoded version regression.
from importlib.metadata import version as _pkg_version

assert ansible_host.__version__ == _pkg_version("ansible-host"), (
f"__version__ ({ansible_host.__version__}) does not match installed "
f"metadata ({_pkg_version('ansible-host')})"
)


def test_dunder_lookup_does_not_dispatch_as_module():
Expand Down
Loading