Replace module - update string comparison method from bytes to unicode (#85785)

This commit is contained in:
Ketan Kelkar 2025-09-10 15:31:22 -07:00 committed by GitHub
parent cf9d78206c
commit 18691ec83f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 74 additions and 6 deletions

View File

@ -0,0 +1,3 @@
minor_changes:
- replace - read/write files in text-mode as unicode chars instead of as bytes
and switch regex matching to unicode chars instead of bytes. (https://github.com/ansible/ansible/pull/85785).

View File

@ -183,14 +183,14 @@ import os
import re
import tempfile
from ansible.module_utils.common.text.converters import to_text, to_bytes
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.basic import AnsibleModule
def write_changes(module, contents, path):
def write_changes(module, contents, path, encoding='utf-8'):
tmpfd, tmpfile = tempfile.mkstemp(dir=module.tmpdir)
with os.fdopen(tmpfd, 'wb') as f:
with os.fdopen(tmpfd, 'w', encoding=encoding) as f:
f.write(contents)
validate = module.params.get('validate', None)
@ -254,8 +254,8 @@ def main():
module.fail_json(rc=257, msg='Path %s does not exist !' % path)
else:
try:
with open(path, 'rb') as f:
contents = to_text(f.read(), errors='surrogate_or_strict', encoding=encoding)
with open(path, 'r', encoding=encoding) as f:
contents = f.read()
except OSError as ex:
raise Exception(f"Unable to read the contents of {path!r}.") from ex
@ -307,7 +307,7 @@ def main():
res_args['backup_file'] = module.backup_local(path)
# We should always follow symlinks so that we change the real file
path = os.path.realpath(path)
write_changes(module, to_bytes(result[0], encoding=encoding), path)
write_changes(module, result[0], path, encoding=encoding)
res_args['msg'], res_args['changed'] = check_file_attrs(module, changed, msg)
module.exit_json(**res_args)

View File

@ -280,3 +280,68 @@
that:
- replace_test9 is failure
- replace_test9.msg.startswith("Unable to process replace")
# test replace operation in non-utf8 encoded files
- name: create test file encoded in cp273
lineinfile:
path: "{{ remote_tmp_dir }}/test-encoding-file.txt"
create: True
line: "Test line encoded in cp273"
state: present
encoding: cp273
- name: stat the new test file
stat:
path: "{{ remote_tmp_dir }}/test-encoding-file.txt"
register: replace_test10
- name: validate test file content
assert:
that:
- replace_test10.stat.exists
- replace_test10.stat.checksum == 'e0bf2bdca94727d03483a9adab66543bcec4b99a'
- name: replace only the 'e' in 'line' with a '3' using both the before and after options
replace:
path: "{{ remote_tmp_dir }}/test-encoding-file.txt"
before: 'encoded'
after: 'Test'
regexp: 'e'
replace: '3'
encoding: cp273
register: replace_test11
- name: stat the modified file
stat:
path: "{{ remote_tmp_dir }}/test-encoding-file.txt"
register: replace_test12
- name: validate the test file content is modified as expected.
assert:
that:
- replace_test11.msg == "1 replacements made"
- replace_test12.stat.exists
- replace_test12.stat.checksum == '485e97f6e38e50680228b8d49e1eb23160f19fdc'
- name: idempotence check - replace only the 'e' 'line' with a '3' again
replace:
path: "{{ remote_tmp_dir }}/test-encoding-file.txt"
before: 'encoded'
after: 'Test'
regexp: 'e'
replace: '3'
encoding: cp273
register: replace_test13
- name: stat the un-modified file
stat:
path: "{{ remote_tmp_dir }}/test-encoding-file.txt"
register: replace_test14
- name: validate the test content is unchanged
assert:
that:
- replace_test13.changed == False
- replace_test14.stat.exists
- replace_test14.stat.checksum == '485e97f6e38e50680228b8d49e1eb23160f19fdc'