Repository: google/mobly

Issue:
yaml.load_all is unsafe with default loader
tests/mobly/output_test.py::OutputTest::test_teardown_class_output
  T:\src\github\mobly\tests\mobly\output_test.py:258: YAMLLoadWarning: 
    *** Calling yaml.load_all() without Loader=... is deprecated.
    *** The default Loader is unsafe.
    *** Please read https://msg.pyyaml.org/load for full details.
    for entry in yaml.load_all(f):

tests/mobly/records_test.py::RecordsTest::test_summary_user_data
  T:\src\github\mobly\tests\mobly\records_test.py:401: YAMLLoadWarning: 
    *** Calling yaml.load_all() without Loader=... is deprecated.
    *** The default Loader is unsafe.
    *** Please read https://msg.pyyaml.org/load for full details.
    for c in yaml.load_all(f):

tests/mobly/records_test.py::RecordsTest::test_summary_write_dump
  T:\src\github\mobly\tests\mobly\records_test.py:364: YAMLLoadWarning: 
    *** Calling yaml.load() without Loader=... is deprecated.
    *** The default Loader is unsafe.
    *** Please read https://msg.pyyaml.org/load for full details.
    content = yaml.load(f)

tests/mobly/records_test.py::RecordsTest::test_summary_write_dump_with_unicode
  T:\src\github\mobly\tests\mobly\records_test.py:383: YAMLLoadWarning: 
    *** Calling yaml.load() without Loader=... is deprecated.
    *** The default Loader is unsafe.
    *** Please read https://msg.pyyaml.org/load for full details.
    content = yaml.load(f)

tests/mobly/test_runner_test.py::TestRunnerTest::test_summary_file_entries
  T:\src\github\mobly\tests\mobly\test_runner_test.py:135: YAMLLoadWarning: 
    *** Calling yaml.load_all() without Loader=... is deprecated.
    *** The default Loader is unsafe.
    *** Please read https://msg.pyyaml.org/load for full details.
    summary_entries = list(yaml.load_all(f))



Discussion:
The alternative API was only added a week ago
https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation

So let's wait for now.

Resolving patch:
diff --git a/mobly/config_parser.py b/mobly/config_parser.py
--- a/mobly/config_parser.py
+++ b/mobly/config_parser.py
@@ -152,7 +152,7 @@ def _load_config_file(path):
         A dict that represents info in the config file.
     """
     with io.open(utils.abs_path(path), 'r', encoding='utf-8') as f:
-        conf = yaml.load(f)
+        conf = yaml.safe_load(f)
         return conf
 
 


Test patch:
diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py
--- a/tests/mobly/base_test_test.py
+++ b/tests/mobly/base_test_test.py
@@ -148,8 +148,8 @@ def test_never(self):
 
         bt_cls = MockBaseTest(self.mock_test_cls_configs)
         expected_msg = (
-            'Test method name not_a_test_something does not follow '
-            'naming convention test_\*, abort.')
+            r'Test method name not_a_test_something does not follow '
+            r'naming convention test_\*, abort.')
         with self.assertRaisesRegex(base_test.Error, expected_msg):
             bt_cls.run()
 
@@ -186,8 +186,8 @@ def test_never(self):
 
         bt_cls = MockBaseTest(self.mock_test_cls_configs)
         expected_msg = (
-            'Test method name not_a_test_something does not follow '
-            'naming convention test_\*, abort.')
+            r'Test method name not_a_test_something does not follow '
+            r'naming convention test_\*, abort.')
         with self.assertRaisesRegex(base_test.Error, expected_msg):
             bt_cls.run(test_names=["not_a_test_something"])
 
@@ -1994,7 +1994,7 @@ def test_something(self):
         self.assertEqual(actual_record.test_name, "test_something")
         hit = False
         with io.open(self.summary_file, 'r', encoding='utf-8') as f:
-            for c in yaml.load_all(f):
+            for c in yaml.safe_load_all(f):
                 if c['Type'] != records.TestSummaryEntryType.USER_DATA.value:
                     continue
                 hit = True
diff --git a/tests/mobly/output_test.py b/tests/mobly/output_test.py
--- a/tests/mobly/output_test.py
+++ b/tests/mobly/output_test.py
@@ -232,7 +232,7 @@ def test_basic_output(self):
          info_log_path) = self.assert_output_logs_exist(output_dir)
         summary_entries = []
         with io.open(summary_file_path, 'r', encoding='utf-8') as f:
-            for entry in yaml.load_all(f):
+            for entry in yaml.safe_load_all(f):
                 self.assertTrue(entry['Type'])
                 summary_entries.append(entry)
         self.assert_log_contents(debug_log_path, whitelist=['DEBUG', 'INFO'])
@@ -255,7 +255,7 @@ def test_teardown_class_output(self):
         with io.open(summary_file_path, 'r', encoding='utf-8') as f:
             raw_content = f.read()
             f.seek(0)
-            for entry in yaml.load_all(f):
+            for entry in yaml.safe_load_all(f):
                 if (entry['Type'] == 'Record'
                         and entry[records.TestResultEnums.RECORD_NAME] ==
                         'teardown_class'):
diff --git a/tests/mobly/records_test.py b/tests/mobly/records_test.py
--- a/tests/mobly/records_test.py
+++ b/tests/mobly/records_test.py
@@ -361,7 +361,7 @@ def test_summary_write_dump(self):
         writer = records.TestSummaryWriter(dump_path)
         writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
         with io.open(dump_path, 'r', encoding='utf-8') as f:
-            content = yaml.load(f)
+            content = yaml.safe_load(f)
             self.assertEqual(content['Type'],
                              records.TestSummaryEntryType.RECORD.value)
             self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
@@ -380,7 +380,7 @@ def test_summary_write_dump_with_unicode(self):
         writer = records.TestSummaryWriter(dump_path)
         writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
         with io.open(dump_path, 'r', encoding='utf-8') as f:
-            content = yaml.load(f)
+            content = yaml.safe_load(f)
             self.assertEqual(content['Type'],
                              records.TestSummaryEntryType.RECORD.value)
             self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
@@ -398,7 +398,7 @@ def test_summary_user_data(self):
             writer.dump(data, records.TestSummaryEntryType.USER_DATA)
         with io.open(dump_path, 'r', encoding='utf-8') as f:
             contents = []
-            for c in yaml.load_all(f):
+            for c in yaml.safe_load_all(f):
                 contents.append(c)
         for content in contents:
             self.assertEqual(content['Type'],
diff --git a/tests/mobly/test_runner_test.py b/tests/mobly/test_runner_test.py
--- a/tests/mobly/test_runner_test.py
+++ b/tests/mobly/test_runner_test.py
@@ -132,7 +132,7 @@ def test_summary_file_entries(self):
         summary_path = os.path.join(logging.log_path,
                                     records.OUTPUT_FILE_SUMMARY)
         with io.open(summary_path, 'r', encoding='utf-8') as f:
-            summary_entries = list(yaml.load_all(f))
+            summary_entries = list(yaml.safe_load_all(f))
         self.assertEqual(len(summary_entries), 4)
         # Verify the first entry is the list of test names.
         self.assertEqual(summary_entries[0]['Type'],