Skip to content

Commit

Permalink
[stable-2.15] [stable-2.16] Enable directly using AnsibleUnsafeText
Browse files Browse the repository at this point in the history
… with Python `pathlib` (ansible#82510)

* Enable directly using `AnsibleUnsafeText` with Python `pathlib`. Fixes ansible#82414.
(cherry picked from commit c6a652c)

Co-authored-by: Matt Martz <matt@sivel.net>
  • Loading branch information
sivel committed Jan 18, 2024
1 parent 11e5071 commit 2eaaafd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 0 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/unsafe-intern.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bugfixes:
- unsafe data - Enable directly using ``AnsibleUnsafeText`` with Python ``pathlib``
(https://github.com/ansible/ansible/issues/82414)
21 changes: 21 additions & 0 deletions lib/ansible/utils/unsafe_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import sys
import types
import warnings
from sys import intern as _sys_intern
from collections.abc import Mapping, Set

from ansible.module_utils._text import to_bytes, to_text
Expand Down Expand Up @@ -369,3 +373,20 @@ def to_unsafe_text(*args, **kwargs):

def _is_unsafe(obj):
return getattr(obj, '__UNSAFE__', False) is True


def _intern(string):
"""This is a monkey patch for ``sys.intern`` that will strip
the unsafe wrapper prior to interning the string.
This will not exist in future versions.
"""
if isinstance(string, AnsibleUnsafeText):
string = string._strip_unsafe()
return _sys_intern(string)


if isinstance(sys.intern, types.BuiltinFunctionType):
sys.intern = _intern
else:
warnings.warn("skipped sys.intern patch; appears to have already been patched", RuntimeWarning)
6 changes: 6 additions & 0 deletions test/lib/ansible_test/_util/target/sanity/import/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,12 @@ def capture_output(capture):
"ignore",
"Python 3.5 support will be dropped in the next release of cryptography. Please upgrade your Python.")

# ansible.utils.unsafe_proxy attempts patching sys.intern generating a warning if it was already patched
warnings.filterwarnings(
"ignore",
"skipped sys.intern patch; appears to have already been patched"
)

try:
yield
finally:
Expand Down
10 changes: 10 additions & 0 deletions test/units/utils/test_unsafe_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type

import pathlib
import sys

from ansible.utils.unsafe_proxy import AnsibleUnsafe, AnsibleUnsafeBytes, AnsibleUnsafeText, wrap_var
from ansible.module_utils.common.text.converters import to_text, to_bytes

Expand Down Expand Up @@ -115,3 +118,10 @@ def test_to_text_unsafe():
def test_to_bytes_unsafe():
assert isinstance(to_bytes(AnsibleUnsafeText(u'foo')), AnsibleUnsafeBytes)
assert to_bytes(AnsibleUnsafeText(u'foo')) == AnsibleUnsafeBytes(b'foo')


def test_unsafe_with_sys_intern():
# Specifically this is actually about sys.intern, test of pathlib
# because that is a specific affected use
assert sys.intern(AnsibleUnsafeText('foo')) == 'foo'
assert pathlib.Path(AnsibleUnsafeText('/tmp')) == pathlib.Path('/tmp')

0 comments on commit 2eaaafd

Please sign in to comment.