When running the unit tests with the locale set to POSIX, some Unicode
tests fail:
$ LC_ALL=POSIX python3 ./tests/runtests.py --unit
[...]
======================================================================
ERROR: test_list_products (unit.modules.test_zypper.ZypperTestCase)
[CPU:0.0%|MEM:73.2%]
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/unit/modules/test_zypper.py", line 236, in
test_list_products
'stdout': get_test_data(filename)
File "tests/unit/modules/test_zypper.py", line 53, in get_test_data
return rfh.read()
File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position
828: ordinal not in range(128)
======================================================================
ERROR: test_non_ascii (unit.templates.test_jinja.TestGetTemplate)
[CPU:0.0%|MEM:73.2%]
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/unit/templates/test_jinja.py", line 341, in test_non_ascii
result = fp.read()
File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 5:
ordinal not in range(128)
======================================================================
ERROR: test_non_ascii_encoding
(unit.templates.test_jinja.TestGetTemplate)
[CPU:0.0%|MEM:73.2%]
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/unit/templates/test_jinja.py", line 303, in
test_non_ascii_encoding
fp_.read(),
File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 5:
ordinal not in range(128)
----------------------------------------------------------------------
Therefore open files in binary mode and explicitly decode them with
utf-8 instead of their default locale.
Without allow_unicode=True, unicode characters are processed through the
str representer and on Python 2 are dumped as a Unicode code point (i.e.
a literal \u0414). This commit makes allow_unicode=True the default in
our salt.utils.yamlloader.safe_dump() helper. It also adds a new
salt.utils.yamlloader.dump() helper which wraps yaml.dump() and also
makes allow_unicode=True the default.
To make importing and using our custom yaml loader/dumper easier, a
convenience module called salt.utils.yaml has been added, which does a
wildcard import from both salt.utils.yamldumper and
salt.utils.yamlloader.
Refs to yaml.load/dump and yaml.safe_load/safe_dump have been updated to
salt.utils.yaml, to ensure that unicode is handled properly.
This makes the 2.x usage invalid syntax and forces the use of print as a
function. This adds the import to the files which I've updated in the
last couple of days but forgot to add it.
PR #42064 modified the YAML dumper to display unicode text as a unicode
literal rather than with the !!python/unicode extension prefix. This
updates the test to reflect the change in Salt's behavior.
The imports were scattered around quite a bit, which made it hard
to see where multiple uses of salt/utils/* imports were being pulled
in.
This PR just adjusts the ordering so it's easier to see what is included
already for the future. (This is particularly useful for catching misuses
of salt.utils.__init__.py functions.)
This PR is part of what will be an ongoing effort to use explicit
unicode strings in Salt. Because Python 3 does not suport Python 2's raw
unicode string syntax (i.e. `ur'\d+'`), we must use
`salt.utils.locales.sdecode()` to ensure that the raw string is unicode.
However, because of how `salt/utils/__init__.py` has evolved into the
hulking monstrosity it is today, this means importing a large module in
places where it is not needed, which could negatively impact
performance. For this reason, this PR also breaks out some of the
functions from `salt/utils/__init__.py` into new/existing modules under
`salt/utils/`. The long term goal will be that the modules within this
directory do not depend on importing `salt.utils`.
A summary of the changes in this PR is as follows:
* Moves the following functions from `salt.utils` to new locations
(including a deprecation warning if invoked from `salt.utils`):
`to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`,
`dequote`, `is_hex`, `is_bin_str`, `rand_string`,
`contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`,
`which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`,
`is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`,
`is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`,
`is_openbsd`, `is_aix`
* Moves the functions already deprecated by @rallytime to the bottom of
`salt/utils/__init__.py` for better organization, so we can keep the
deprecated ones separate from the ones yet to be deprecated as we
continue to break up `salt.utils`
* Updates `salt/*.py` and all files under `salt/client/` to use explicit
unicode string literals.
* Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils
import foo` becomes `import salt.utils.foo as foo`).
* Renames the `test.rand_str` function to `test.random_hash` to more
accurately reflect what it does
* Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`)
such that it returns a string matching the passed size. Previously
this function would get `size` bytes from `os.urandom()`,
base64-encode it, and return the result, which would in most cases not
be equal to the passed size.
We can't rely on lists having the same order in Python3 the same
way we rely on them in Python2. If we sort them first, and then
compare them, this test will be more reliable.
Due to a bug in the equality handler, this test was failing on
CentOS 6 running Python 2.7.13. This PR splits up the test assertions
into several different pieces in order to cover all the possible
use cases, but also pass on CentOS 6.