From 0ba737b9adea3556e62b4648ca4a27d7cc0bc972 Mon Sep 17 00:00:00 2001 From: garenchan Date: Mon, 26 Apr 2021 11:56:16 +0800 Subject: [PATCH] Fix optionfiles parsing error with include directive --- lib/mysql/connector/optionfiles.py | 5 +++++ tests/data/option_files/my_overwrite.cnf | 4 ++++ tests/test_optionfiles.py | 28 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 tests/data/option_files/my_overwrite.cnf diff --git a/lib/mysql/connector/optionfiles.py b/lib/mysql/connector/optionfiles.py index 74b2a43..4e759eb 100644 --- a/lib/mysql/connector/optionfiles.py +++ b/lib/mysql/connector/optionfiles.py @@ -202,6 +202,7 @@ def _parse_options(self, files): raise ValueError("Failed reading file '{0}': {1}".format( file_, str(exc))) + files.reverse() read_files = self.read(files) not_read_files = set(files) - set(read_files) if not_read_files: @@ -224,6 +225,10 @@ def read(self, filenames): # pylint: disable=W0221 out_file = io.StringIO() for line in codecs.open(filename, encoding='utf-8'): line = line.strip() + # Skip lines that begin with "!includedir" or "!include" + if line.startswith('!include'): + continue + match_obj = self.OPTCRE.match(line) if not self.SECTCRE.match(line) and match_obj: optname, delimiter, optval = match_obj.group('option', diff --git a/tests/data/option_files/my_overwrite.cnf b/tests/data/option_files/my_overwrite.cnf new file mode 100644 index 0000000..0342ff5 --- /dev/null +++ b/tests/data/option_files/my_overwrite.cnf @@ -0,0 +1,4 @@ +!include my.cnf + +[mysqld] +port=1002 diff --git a/tests/test_optionfiles.py b/tests/test_optionfiles.py index f96a800..5a5e22a 100644 --- a/tests/test_optionfiles.py +++ b/tests/test_optionfiles.py @@ -28,6 +28,7 @@ import logging import os +import tempfile import tests from mysql.connector import connect @@ -214,3 +215,30 @@ def test_read_option_files(self): self.assertEqual(exp, result) self.assertRaises(ValueError, connect, option_files='dummy_file.cnf') + + def test_read_option_files_with_include(self): + my_cnf_name = 'my.cnf' + my_cnf = os.path.join(self.option_file_dir, my_cnf_name) + my_overwrite = os.path.join(self.option_file_dir, 'my_overwrite.cnf') + + # Use a temporary file to change the relative path of + # include directive to an absolute path + my_overwrite_tf = tempfile.NamedTemporaryFile(delete=False) + with open(my_overwrite, 'r') as fp: + data = fp.read() + data = data.replace(my_cnf_name, my_cnf) + my_overwrite_tf.write(data.encode()) + + result = read_option_files(option_files=my_overwrite_tf.name, + option_groups='mysqld') + + # option in the overwrite file + port_exp = 1002 + self.assertEqual(port_exp, result['port']) + + # option in the include file + user_exp = 'mysql' + self.assertEqual(user_exp, result['user']) + + # delete temporary file + os.unlink(my_overwrite_tf.name)