The Black -> Ruff migration (AAP-85334) installs a bare, unpinned
`ruff` in four places: requirements_dev.txt, both tox.ini linters
envs, and the devel image Dockerfile. CI's api-lint job resolves the
latest release on every run.
Ruff treats minor releases as breaking by policy: that is where the
yearly formatter style guide lands (0.9.0, 0.15.0) and where rules are
promoted or change behavior. Left unpinned, the next minor turns
unrelated PRs and quiet stable branches red with no code change.
Pin to ~=0.16.0 everywhere, and add `required-version` to
[tool.ruff] so a developer's mismatched local ruff (pre-commit.sh uses
whatever is on PATH) is refused instead of silently reformatting.
Patch releases within 0.16.x still flow, so bug fixes arrive without
a bump; the floor moves through a reviewed PR when 0.17 lands.
Claude-Session: https://claude.ai/code/session_011rb7ruHixj48khUNXxxqPG
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Migrate Python linting and formatting toolchain from Black (formatter)
and Flake8 (linter) to Ruff, which provides both in a single tool.
- pyproject.toml: remove [tool.black], add [tool.ruff] config sections
- tox.ini: replace black+flake8 deps/commands with ruff in linters env
- awxkit/tox.ini: replace flake8 with ruff in lint env
- Makefile: replace `black` target with `format` + `lint`, keep `black`
as legacy alias, update `check` and `api-lint`
- pre-commit.sh: use `ruff format --check`, honor AWX_IGNORE_RUFF
- requirements_dev.txt: swap black/flake8 for ruff
- Dockerfile.j2: install ruff instead of black
- CONTRIBUTING.md: update tool references
- Fix noqa comments to use # separator instead of ; (ruff requirement)
- Add noqa: F841 for false positive in awxkit/cli/__init__.py
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forward-port of ansible/tower#7537 for the devel branch.
When running awxkit's tox tests, pytest picks up the root pytest.ini
which pulls in pytest-django options (--reuse-db, --nomigrations,
DJANGO_SETTINGS_MODULE) and Django-specific filterwarnings. Since the
awxkit tox environment does not install Django or pytest-django, these
cause test collection to fail.
The root cause is that pytest.ini has absolute priority in pytest's
config discovery — it searches all ancestor directories for pytest.ini
before falling back to tox.ini's [pytest] section. A [pytest] section
in awxkit/tox.ini alone cannot prevent the root config from being used.
Fix by:
- Adding awxkit/pytest.ini to act as the primary config boundary
(pytest.ini has the highest priority in config discovery, so its
presence in awxkit/ stops the upward search before reaching root)
- Adding explicit `test` path argument to the pytest command in
awxkit/tox.ini so pytest discovers tests correctly
- Adding `testpaths` and `python_files` to the [pytest] section in
awxkit/tox.ini as a secondary config boundary
- Adding awxkit/conftest.py that registers the Django-specific CLI
options and INI keys as harmless no-ops, as a further safety net
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* update to Python 3.12
* remove use of utcnow
* switch to timezone.utc
datetime.UTC is an alias of datetime.timezone.utc. if we're doing the double import for datetime it's more straightforward to just import timezone as well and get it directly
* debug python env version issue
* change python version
* pin to SHA and remove debug portion
In essence, this configures Python to turn any warnings emitted in
runtime into errors[[1]]. This is the best practice that allows
reacting to future deprecation announcements that are coming from the
dependencies (direct, or transitive, or even CPython itself)[[2]].
The typical workflow looks like this:
1. If a dependency is updated an a warning is hit in tests, the
deprecated thing should be replaced with newer APIs.
2. If a dependency is transitive or we have no control over it
otherwise, the specific warning and a regex matching its message,
plus the module reference (where possible) can be added to the
list of temporary ignores in `pytest.ini`.
3. The list of temporary ignores should be reevaluated periodically,
including when dependency re-pinning in lockfile is happening.
[1]: https://docs.python.org/3/using/cmdline.html#cmdoption-W
[2]: https://pytest-with-eric.com/configuration/pytest-ignore-warnings/
- Django's PostgreSQL JSONField wraps values in a JsonAdapter, so deal
with that when it happens. This goes away in Django 3.1.
- Setting related *_id fields clears the actual relation field, so
trying to fake objects for tests is a problem
- Instance.objects.me() was inappropriately creating stub objects
every time while running tests, but some of our tests now create
real db objects. Ditch that logic and use a proper fixture where needed.
- awxkit tox.ini was pinned at Python 3.8
- remove flake8 as an install requirements (it's only used for tests)
- vendor toposort, which is Apache 2.0 licensed (and very small)
- change websocket-client to a setuptools optional dependency, which you
can install via:
pip install "./awxkit[websockets]"
- add `jq` and `tabulate` under an additional optional setuptools
dependency:
pip install "./awxkit[formatting]"
- remove `cryptography`, which is only used for random RSA generation
(unused by the CLI)