mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-25 06:10:22 -07:00
Give native strings to selinux library functions. (#17184)
* Give native strings to selinux library functions. SELinux takes pathnames as native strings. That means we need to convert to bytes on python2 and convert to text on python3. Fixes #17155 * Read kitchen documentation, make module_utils params more like kitchen API * Remove none nonstring strategy and add strict * Raise TypeError on invalid nonstring strategy * Document to_native() * Make unittests for testing module_utils.text
This commit is contained in:
parent
384a01fcff
commit
57701d7115
4 changed files with 242 additions and 29 deletions
171
lib/ansible/module_utils/_text.py
Normal file
171
lib/ansible/module_utils/_text.py
Normal file
|
@ -0,0 +1,171 @@
|
|||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
#
|
||||
# Copyright (c), Toshio Kuratomi <a.badger@gmail.com>, 2016
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
"""
|
||||
.. warn:: This module_util is currently internal implementation.
|
||||
We want to evaluate this code for stability and API suitability before
|
||||
making backwards compatibility guarantees. The API may change between
|
||||
releases. Do not use this unless you are willing to port your module code.
|
||||
"""
|
||||
|
||||
from ansible.module_utils.six import PY3, text_type, binary_type
|
||||
|
||||
def to_bytes(obj, encoding='utf-8', errors=None, nonstring='simplerepr'):
|
||||
"""Make sure that a string is a byte string
|
||||
|
||||
:arg obj: An object to make sure is a byte string. In most cases this
|
||||
will be either a text string or a byte string. However, with
|
||||
``nonstring='simplerepr'``, this can be used as a traceback-free
|
||||
version of ``str(obj)``.
|
||||
:kwarg encoding: The encoding to use to transform from a text string to
|
||||
a byte string. Defaults to using 'utf-8'.
|
||||
:kwarg errors: The error handler to use if the text string is not
|
||||
encodable using the specified encoding. Any valid `codecs error
|
||||
handler <https://docs.python.org/2/library/codecs.html#codec-base-classes>`_
|
||||
may be specified. On Python3 this defaults to 'surrogateescape'. On
|
||||
Python2, this defaults to 'replace'.
|
||||
:kwarg nonstring: The strategy to use if a nonstring is specified in
|
||||
``obj``. Default is 'simplerepr'. Valid values are:
|
||||
|
||||
:simplerepr: The default. This takes the ``str`` of the object and
|
||||
then returns the bytes version of that string.
|
||||
:empty: Return an empty byte string
|
||||
:passthru: Return the object passed in
|
||||
:strict: Raise a :exc:`TypeError`
|
||||
|
||||
:returns: Typically this returns a byte string. If a nonstring object is
|
||||
passed in this may be a different type depending on the strategy
|
||||
specified by nonstring. This will never return a text string.
|
||||
|
||||
.. note:: If passed a byte string, this function does not check that the
|
||||
string is valid in the specified encoding. If it's important that the
|
||||
byte string is in the specified encoding do::
|
||||
|
||||
encoded_string = to_bytes(to_text(input_string, 'latin-1'), 'utf-8')
|
||||
"""
|
||||
if isinstance(obj, binary_type):
|
||||
return obj
|
||||
|
||||
if errors is None:
|
||||
if PY3:
|
||||
errors = 'surrogateescape'
|
||||
else:
|
||||
errors = 'replace'
|
||||
|
||||
if isinstance(obj, text_type):
|
||||
return obj.encode(encoding, errors)
|
||||
|
||||
# Note: We do these last even though we have to call to_bytes again on the
|
||||
# value because we're optimizing the common case
|
||||
if nonstring == 'simplerepr':
|
||||
value = str(obj)
|
||||
elif nonstring == 'passthru':
|
||||
return obj
|
||||
elif nonstring == 'empty':
|
||||
# python2.4 doesn't have b''
|
||||
return to_bytes('')
|
||||
elif nonstring == 'strict':
|
||||
raise TypeError('obj must be a string type')
|
||||
else:
|
||||
raise TypeError('Invalid value %s for to_bytes\' nonstring parameter' % nonstring)
|
||||
|
||||
return to_bytes(value, encoding, errors)
|
||||
|
||||
def to_text(obj, encoding='utf-8', errors=None, nonstring='simplerepr'):
|
||||
"""Make sure that a string is a text string
|
||||
|
||||
:arg obj: An object to make sure is a text string. In most cases this
|
||||
will be either a text string or a byte string. However, with
|
||||
``nonstring='simplerepr'``, this can be used as a traceback-free
|
||||
version of ``str(obj)``.
|
||||
:kwarg encoding: The encoding to use to transform from a byte string to
|
||||
a text string. Defaults to using 'utf-8'.
|
||||
:kwarg errors: The error handler to use if the byte string is not
|
||||
decodable using the specified encoding. Any valid `codecs error
|
||||
handler <https://docs.python.org/2/library/codecs.html#codec-base-classes>`_
|
||||
may be specified. On Python3 this defaults to 'surrogateescape'. On
|
||||
Python2, this defaults to 'replace'.
|
||||
:kwarg nonstring: The strategy to use if a nonstring is specified in
|
||||
``obj``. Default is 'simplerepr'. Valid values are:
|
||||
|
||||
:simplerepr: The default. This takes the ``str`` of the object and
|
||||
then returns the text version of that string.
|
||||
:empty: Return an empty text string
|
||||
:passthru: Return the object passed in
|
||||
:strict: Raise a :exc:`TypeError`
|
||||
|
||||
:returns: Typically this returns a text string. If a nonstring object is
|
||||
passed in this may be a different type depending on the strategy
|
||||
specified by nonstring. This will never return a byte string.
|
||||
"""
|
||||
if isinstance(obj, text_type):
|
||||
return obj
|
||||
|
||||
if errors is None:
|
||||
if PY3:
|
||||
errors = 'surrogateescape'
|
||||
else:
|
||||
errors = 'replace'
|
||||
|
||||
if isinstance(obj, binary_type):
|
||||
return obj.decode(encoding, errors)
|
||||
|
||||
# Note: We do these last even though we have to call to_text again on the
|
||||
# value because we're optimizing the common case
|
||||
if nonstring == 'simplerepr':
|
||||
value = str(obj)
|
||||
elif nonstring == 'passthru':
|
||||
return obj
|
||||
elif nonstring == 'empty':
|
||||
return u''
|
||||
elif nonstring == 'strict':
|
||||
raise TypeError('obj must be a string type')
|
||||
else:
|
||||
raise TypeError('Invalid value %s for to_text\'s nonstring parameter' % nonstring)
|
||||
|
||||
return to_text(value, encoding, errors)
|
||||
|
||||
#: :py:func:`to_native`
|
||||
#: Transform a variable into the native str type for the python version
|
||||
#:
|
||||
#: On Python2, this is an alias for
|
||||
#: :func:`~ansible.module_utils.to_bytes`. On Python3 it is an alias for
|
||||
#: :func:`~ansible.module_utils.to_text`. It makes it easier to
|
||||
#: transform a variable into the native str type for the python version
|
||||
#: the code is running on. Use this when constructing the message to
|
||||
#: send to exceptions or when dealing with an API that needs to take
|
||||
#: a native string. Example::
|
||||
#:
|
||||
#: try:
|
||||
#: 1//0
|
||||
#: except ZeroDivisionError as e:
|
||||
#: raise MyException('Encountered and error: %s' % to_native(e))
|
||||
if PY3:
|
||||
to_native = to_text
|
||||
else:
|
||||
to_native = to_bytes
|
Loading…
Add table
Add a link
Reference in a new issue