--- /dev/null
+diff --git a/salt/modules/dockercompose.py b/salt/modules/dockercompose.py
+index 61e937536c..0f37e0d43a 100644
+--- a/salt/modules/dockercompose.py
++++ b/salt/modules/dockercompose.py
+@@ -241,7 +241,7 @@ def __load_docker_compose(path):
+ None, None)
+ try:
+ with salt.utils.files.fopen(file_path, 'r') as fl:
+- loaded = yaml.load(fl)
++ loaded = yaml.safe_load(fl)
+ except EnvironmentError:
+ return None, __standardize_result(False,
+ 'Could not read {0}'.format(file_path),
+@@ -371,7 +371,7 @@ def __load_compose_definitions(path, definition):
+ None, None)
+ else:
+ try:
+- loaded_definition = yaml.load(definition)
++ loaded_definition = yaml.safe_load(definition)
+ except yaml.YAMLError as yerr:
+ msg = 'Could not parse {0} {1}'.format(definition, yerr)
+ return None, None, __standardize_result(False, msg,
+diff --git a/tests/integration/utils/test_win_runas.py b/tests/integration/utils/test_win_runas.py
+index 3042a77991..d4057a4d03 100644
+--- a/tests/integration/utils/test_win_runas.py
++++ b/tests/integration/utils/test_win_runas.py
+@@ -539,7 +539,7 @@ class RunAsTest(ModuleCase):
+ win32serviceutil.StartService('test service')
+ wait_for_service('test service')
+ with salt.utils.files.fopen(RUNAS_OUT, 'r') as fp:
+- ret = yaml.load(fp)
++ ret = yaml.safe_load(fp)
+ assert ret['retcode'] == 1, ret
+
+ @with_system_user('test-runas', on_existing='delete', delete=True,
+@@ -560,7 +560,7 @@ class RunAsTest(ModuleCase):
+ win32serviceutil.StartService('test service')
+ wait_for_service('test service')
+ with salt.utils.files.fopen(RUNAS_OUT, 'r') as fp:
+- ret = yaml.load(fp)
++ ret = yaml.safe_load(fp)
+ assert ret['retcode'] == 1, ret
+
+ @with_system_user('test-runas-admin', on_existing='delete', delete=True,
+@@ -581,7 +581,7 @@ class RunAsTest(ModuleCase):
+ win32serviceutil.StartService('test service')
+ wait_for_service('test service')
+ with salt.utils.files.fopen(RUNAS_OUT, 'r') as fp:
+- ret = yaml.load(fp)
++ ret = yaml.safe_load(fp)
+ assert ret['retcode'] == 0, ret
+
+ @with_system_user('test-runas-admin', on_existing='delete', delete=True,
+@@ -602,7 +602,7 @@ class RunAsTest(ModuleCase):
+ win32serviceutil.StartService('test service')
+ wait_for_service('test service')
+ with salt.utils.files.fopen(RUNAS_OUT, 'r') as fp:
+- ret = yaml.load(fp)
++ ret = yaml.safe_load(fp)
+ assert ret['retcode'] == 0, ret
+
+ def test_runas_service_system_user(self):
+@@ -621,5 +621,5 @@ class RunAsTest(ModuleCase):
+ win32serviceutil.StartService('test service')
+ wait_for_service('test service')
+ with salt.utils.files.fopen(RUNAS_OUT, 'r') as fp:
+- ret = yaml.load(fp)
++ ret = yaml.safe_load(fp)
+ assert ret['retcode'] == 0, ret
+diff --git a/tests/unit/utils/test_schema.py b/tests/unit/utils/test_schema.py
+index a07fcbab6b..79072bb89e 100644
+--- a/tests/unit/utils/test_schema.py
++++ b/tests/unit/utils/test_schema.py
+@@ -5,6 +5,7 @@
+
+ # Import python libs
+ from __future__ import absolute_import, print_function, unicode_literals
++import sys
+ import copy
+
+ # Import Salt Testing Libs
+@@ -506,10 +507,7 @@ class ConfigTestCase(TestCase):
+ {'personal_access_token': 'foo'},
+ Requirements.serialize()
+ )
+- if JSONSCHEMA_VERSION >= _LooseVersion('3.0.0'):
+- self.assertIn('\'ssh_key_file\' is a required property', excinfo.exception.message)
+- else:
+- self.assertIn('is not valid under any of the given schemas', excinfo.exception.message)
++ self.assertIn('\'ssh_key_file\' is a required property', excinfo.exception.message)
+
+ def test_boolean_config(self):
+ item = schema.BooleanItem(title='Hungry', description='Are you hungry?')
+@@ -1733,10 +1731,11 @@ class ConfigTestCase(TestCase):
+
+ with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ jsonschema.validate({'item': {'sides': '4', 'color': 'blue'}}, TestConf.serialize())
+- if JSONSCHEMA_VERSION >= _LooseVersion('3.0.0'):
+- self.assertIn('\'4\' is not of type \'boolean\'', excinfo.exception.message)
++
++ if sys.hexversion >= 0x03000000:
++ self.assertIn("'4' is not of type 'boolean'", excinfo.exception.message)
+ else:
+- self.assertIn('is not valid under any of the given schemas', excinfo.exception.message)
++ self.assertIn("u'4' is not of type u'boolean'", excinfo.exception.message)
+
+ class TestConf(schema.Schema):
+ item = schema.DictItem(
+@@ -1839,10 +1838,10 @@ class ConfigTestCase(TestCase):
+
+ with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ jsonschema.validate({'item': ['maybe']}, TestConf.serialize())
+- if JSONSCHEMA_VERSION >= _LooseVersion('3.0.0'):
+- self.assertIn('\'maybe\' is not one of [\'yes\']', excinfo.exception.message)
++ if sys.hexversion >= 0x03000000:
++ self.assertIn("'maybe' is not one of ['yes']", excinfo.exception.message)
+ else:
+- self.assertIn('is not valid under any of the given schemas', excinfo.exception.message)
++ self.assertIn("u'maybe' is not one of [u'yes']", excinfo.exception.message)
+
+ with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ jsonschema.validate({'item': 2}, TestConf.serialize())
+@@ -1894,10 +1893,10 @@ class ConfigTestCase(TestCase):
+
+ with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ jsonschema.validate({'item': ['maybe']}, TestConf.serialize())
+- if JSONSCHEMA_VERSION >= _LooseVersion('3.0.0'):
+- self.assertIn('\'maybe\' is not one of [\'yes\']', excinfo.exception.message)
++ if sys.hexversion >= 0x03000000:
++ self.assertIn("'maybe' is not one of ['yes']", excinfo.exception.message)
+ else:
+- self.assertIn('is not valid under any of the given schemas', excinfo.exception.message)
++ self.assertIn("u'maybe' is not one of [u'yes']", excinfo.exception.message)
+
+ with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ jsonschema.validate({'item': 2}, TestConf.serialize())
--- /dev/null
+# Copyright 1999-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+PYTHON_COMPAT=( python2_7 python3_6 )
+
+inherit eutils systemd distutils-r1
+
+DESCRIPTION="Salt is a remote execution and configuration manager"
+HOMEPAGE="https://www.saltstack.com/resources/community/
+ https://github.com/saltstack"
+
+if [[ ${PV} == 9999* ]]; then
+ inherit git-r3
+ EGIT_REPO_URI="git://github.com/${PN}stack/${PN}.git"
+ EGIT_BRANCH="develop"
+ SRC_URI=""
+ KEYWORDS=""
+else
+ SRC_URI="mirror://pypi/${PN:0:1}/${PN}/${P}.tar.gz"
+ KEYWORDS="~amd64 ~x86"
+fi
+
+LICENSE="Apache-2.0"
+SLOT="0"
+IUSE="cherrypy ldap libcloud libvirt gnupg keyring mako mongodb mysql neutron nova"
+IUSE+=" openssl portage profile redis selinux test timelib raet +zeromq vim-syntax"
+
+RDEPEND="sys-apps/pciutils
+ dev-python/jinja[${PYTHON_USEDEP}]
+ dev-python/libnacl[${PYTHON_USEDEP}]
+ >=dev-python/msgpack-0.3[${PYTHON_USEDEP}]
+ dev-python/pyyaml[${PYTHON_USEDEP}]
+ dev-python/markupsafe[${PYTHON_USEDEP}]
+ >=dev-python/requests-1.0.0[${PYTHON_USEDEP}]
+ dev-python/setuptools[${PYTHON_USEDEP}]
+ >=www-servers/tornado-4.2.1[${PYTHON_USEDEP}]
+ <www-servers/tornado-5.0[${PYTHON_USEDEP}]
+ virtual/python-futures[${PYTHON_USEDEP}]
+ libcloud? ( >=dev-python/libcloud-0.14.0[${PYTHON_USEDEP}] )
+ mako? ( dev-python/mako[${PYTHON_USEDEP}] )
+ ldap? ( dev-python/python-ldap[${PYTHON_USEDEP}] )
+ libvirt? ( dev-python/libvirt-python[${PYTHON_USEDEP}] )
+ openssl? (
+ dev-libs/openssl:0=[-bindist]
+ dev-python/pyopenssl[${PYTHON_USEDEP}]
+ )
+ raet? (
+ >=dev-python/libnacl-1.0.0[${PYTHON_USEDEP}]
+ >=dev-python/ioflo-1.1.7[${PYTHON_USEDEP}]
+ >=dev-python/raet-0.6.0[${PYTHON_USEDEP}]
+ )
+ zeromq? (
+ >=dev-python/pyzmq-2.2.0[${PYTHON_USEDEP}]
+ dev-python/pycryptodome[${PYTHON_USEDEP}]
+ )
+ cherrypy? ( >=dev-python/cherrypy-3.2.2[${PYTHON_USEDEP}] )
+ mongodb? ( dev-python/pymongo[${PYTHON_USEDEP}] )
+ portage? ( sys-apps/portage[${PYTHON_USEDEP}] )
+ keyring? ( dev-python/keyring[${PYTHON_USEDEP}] )
+ mysql? ( dev-python/mysql-python[$(python_gen_usedep 'python2*')] )
+ redis? ( dev-python/redis-py[${PYTHON_USEDEP}] )
+ selinux? ( sec-policy/selinux-salt )
+ timelib? ( dev-python/timelib[$(python_gen_usedep 'python2*')] )
+ nova? ( >=dev-python/python-novaclient-2.17.0[${PYTHON_USEDEP}] )
+ neutron? ( >=dev-python/python-neutronclient-2.3.6[${PYTHON_USEDEP}] )
+ gnupg? ( dev-python/python-gnupg[${PYTHON_USEDEP}] )
+ profile? ( dev-python/yappi[${PYTHON_USEDEP}] )
+ vim-syntax? ( app-vim/salt-vim )"
+DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]
+ test? (
+ >=dev-python/pytest-salt-2018.12.8[${PYTHON_USEDEP}]
+ >=dev-python/jsonschema-3.0[${PYTHON_USEDEP}]
+ dev-python/pytest-helpers-namespace[${PYTHON_USEDEP}]
+ dev-python/psutil[${PYTHON_USEDEP}]
+ dev-python/pytest[${PYTHON_USEDEP}]
+ dev-python/pytest-catchlog[${PYTHON_USEDEP}]
+ dev-python/pip[${PYTHON_USEDEP}]
+ dev-python/virtualenv[${PYTHON_USEDEP}]
+ >=dev-python/mock-2.0.0[${PYTHON_USEDEP}]
+ dev-python/timelib[$(python_gen_usedep 'python2*')]
+ >=dev-python/boto-2.32.1[${PYTHON_USEDEP}]
+ !x86? ( >=dev-python/boto3-1.2.1[${PYTHON_USEDEP}] )
+ >=dev-python/moto-0.3.6[${PYTHON_USEDEP}]
+ >=dev-python/SaltTesting-2016.5.11[${PYTHON_USEDEP}]
+ >=dev-python/libcloud-0.14.0[${PYTHON_USEDEP}]
+ ${RDEPEND}
+ )"
+
+DOCS=( README.rst AUTHORS )
+
+REQUIRED_USE="|| ( raet zeromq )"
+RESTRICT="x86? ( test )"
+
+PATCHES=(
+ "${FILESDIR}/salt-2017.7.0-dont-realpath-tmpdir.patch"
+ "${FILESDIR}/salt-2019.2.0-tests.patch"
+ "${FILESDIR}/salt-2019.2.0-skip-tests-that-oom-machine.patch"
+ "${FILESDIR}/salt-2019.2.2-newer-deps.patch"
+ "${FILESDIR}/salt-2019.2.2-workaround-broken-mock-on-py2.patch"
+)
+
+python_prepare() {
+ # remove tests with external dependencies that may not be available
+ rm tests/unit/{test_zypp_plugins.py,utils/test_extend.py} || die
+ rm tests/unit/modules/test_{file,boto_{vpc,secgroup,elb}}.py || die
+ rm tests/unit/states/test_boto_vpc.py || die
+
+ # allow the use of the renamed msgpack
+ sed -i '/^msgpack/d' requirements/base.txt || die
+}
+
+python_install_all() {
+ local svc
+ USE_SETUPTOOLS=1 distutils-r1_python_install_all
+
+ for svc in minion master syndic api; do
+ newinitd "${FILESDIR}"/${svc}-initd-4 salt-${svc}
+ newconfd "${FILESDIR}"/${svc}-confd-1 salt-${svc}
+ systemd_dounit "${FILESDIR}"/salt-${svc}.service
+ done
+
+ insinto /etc/${PN}
+ doins -r conf/*
+}
+
+python_test() {
+ local tempdir
+ # testsuite likes lots of files
+ ulimit -n 3072 || die
+
+ # ${T} is too long a path for the tests to work
+ tempdir="$(mktemp -du --tmpdir=/tmp salt-XXX)"
+ mkdir "${T}/$(basename "${tempdir}")"
+ mkdir "${BUILD_DIR}"/../{templates,conf/cloud.{providers,profiles,maps}.d} || die
+
+ (
+ cleanup() {
+ rm -f "${tempdir}"
+ rmdir "${BUILD_DIR}"/../{templates,conf/cloud.{providers,profiles,maps}.d} || die
+ }
+
+ trap cleanup EXIT
+
+ addwrite "${tempdir}"
+ ln -s "$(realpath --relative-to=/tmp "${T}/$(basename "${tempdir}")")" "${tempdir}"
+
+ USE_SETUPTOOLS=1 SHELL="/bin/bash" \
+ TMPDIR="${tempdir}" \
+ ${EPYTHON} tests/runtests.py \
+ --unit-tests --no-report --verbose
+
+ ) || die "testing failed"
+}