Summary
We recently migrated from a simple requirements.txt file to the by now ubiquitous pyproject.toml installation. The location of this project is on the local filesystem of the target machine after extraction of a remote tar.gz release.
Since this migration, we see an idempotency flag of 1 on the virtualenv pip that is caused by the last output of the pyproject.toml pip install /path/to/package, triggered by a 'Successfully installed' of the base package.
Builtin pip sees this as a change, because there is no out_freeze_before which is caused by the fact that we no longer use requirements and name does not look like a vcs url. Nevertheless, a comparisson of out_freeze_before and out_freeze_after would correctly reveal no changes in this case.
The name of the package looks like /path/to/package[test] so adding ^/ to _VCS_RE would already help a lot in our case, but I'm not sure whether any non-local package could also start with / and others might specify the location relative and still be hit with a change?
Issue Type
Bug Report
Component Name
ansible.builtin.pip
Ansible Version
$ ansible --version
ansible [core 2.20.1]
config file = /***/ansible.cfg
configured module search path = ['/***/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/martin/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.14.4 (main, Apr 8 2026, 04:02:31) [GCC 15.2.0] (/usr/bin/python3)
jinja version = 3.1.6
pyyaml version = 6.0.3 (with libyaml v0.2.5)
Configuration
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
ACHE_PLUGIN(/***/ansible.cfg) = yaml
CACHE_PLUGIN_CONNECTION(/***/ansible.cfg) = .ansible/facts
CALLBACKS_ENABLED(/***/ansible.cfg) = ['profile_tasks']
CONFIG_FILE() = /***/ansible.cfg
DEFAULT_BECOME(/***/ansible.cfg) = True
DEFAULT_FORKS(/***/ansible.cfg) = 25
DEFAULT_GATHERING(/***/ansible.cfg) = smart
DEFAULT_LOAD_CALLBACK_PLUGINS(/***/ansible.cfg) = True
DEFAULT_STDOUT_CALLBACK(/***/ansible.cfg) = yaml
DEFAULT_UNDEFINED_VAR_BEHAVIOR(/***/ansible.cfg) = True
DEPRECATION_WARNINGS(/***/ansible.cfg) = True
HOST_KEY_CHECKING(/***/ansible.cfg) = False
INTERPRETER_PYTHON(/***/ansible.cfg) = /usr/bin/python3
MAX_FILE_SIZE_FOR_DIFF(/***/ansible.cfg) = 1044480
GALAXY_SERVERS:
CACHE:
=====
jsonfile:
________
_uri(/***/ansible.cfg) = /***/.ansible/facts
CONNECTION:
==========
paramiko_ssh:
____________
host_key_checking(/***/ansible.cfg) = False
ssh:
___
host_key_checking(/***/ansible.cfg) = False
pipelining(/***/ansible.cfg) = True
ssh_args(/***/ansible.cfg) = -o ControlMaster=auto -o ControlPersist=3600s
OS / Environment
Host: Ubuntu 26.04
Target: Debian GNU/Linux 12
Steps to Reproduce
- Replace requirments.txt with pyproject.toml
- Remove requirements from ansible task
- Add name, pointing to project root on remote filesystem
Expected Results
No changes detected when switching from requirements.txt to pyproject.toml
Actual Results
Changes detected after use of pip module after migration to pyproject.toml:
Output of pip install /path/to/sbs[test]
...
Building wheels for collected packages: sbs
Building wheel for sbs (pyproject.toml): started
Building wheel for sbs (pyproject.toml): finished with status 'done'
Created wheel for sbs: filename=sbs-0.0.0-py3-none-any.whl size=1373588 sha256=34b70435875d2317014f8b8f76cbb37e7de67c1eeec7d73c518e0fa9285726bb
Stored in directory: /tmp/pip-ephem-wheel-cache-yl9xmalr/wheels/d0/ec/9b/163ad8d57bb4b7f0181499046424e21dd138f20e2c1b8484eb
Successfully built sbs
Installing collected packages: sbs
Attempting uninstall: sbs
Found existing installation: sbs 0.0.0
Uninstalling sbs-0.0.0:
Successfully uninstalled sbs-0.0.0
Successfully installed sbs-0.0.0
The final 'Succesully installed ...' triggers the changed state and spoils the idempotency.
Code of Conduct
Summary
We recently migrated from a simple requirements.txt file to the by now ubiquitous pyproject.toml installation. The location of this project is on the local filesystem of the target machine after extraction of a remote tar.gz release.
Since this migration, we see an idempotency flag of 1 on the virtualenv pip that is caused by the last output of the pyproject.toml
pip install /path/to/package, triggered by a 'Successfully installed' of the base package.Builtin pip sees this as a change, because there is no
out_freeze_beforewhich is caused by the fact that we no longer userequirementsandnamedoes not look like a vcs url. Nevertheless, a comparisson ofout_freeze_beforeandout_freeze_afterwould correctly reveal no changes in this case.The name of the package looks like
/path/to/package[test]so adding^/to_VCS_REwould already help a lot in our case, but I'm not sure whether any non-local package could also start with/and others might specify the location relative and still be hit with a change?Issue Type
Bug Report
Component Name
ansible.builtin.pip
Ansible Version
Configuration
OS / Environment
Host: Ubuntu 26.04
Target: Debian GNU/Linux 12
Steps to Reproduce
Expected Results
No changes detected when switching from requirements.txt to pyproject.toml
Actual Results
Code of Conduct