|
14 | 14 | # You should have received a copy of the GNU General Public License
|
15 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16 | 16 |
|
| 17 | +import glob |
17 | 18 | import locale
|
18 | 19 | import os
|
19 | 20 | import pty
|
20 | 21 | import shutil
|
21 | 22 | import sys
|
22 | 23 | import tempfile
|
23 | 24 | import unittest
|
24 |
| -from io import StringIO |
25 | 25 |
|
26 | 26 | from tests.common import (
|
27 | 27 | RunContext,
|
@@ -607,20 +607,32 @@ def test_github_actions_detection(self):
|
607 | 607 | (ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
|
608 | 608 |
|
609 | 609 | def test_run_read_from_stdin(self):
|
610 |
| - # prepares stdin with an invalid yaml string so that we can check |
611 |
| - # for its specific error, and be assured that stdin was read |
612 | 610 | self.addCleanup(setattr, sys, 'stdin', sys.__stdin__)
|
613 |
| - sys.stdin = StringIO( |
614 |
| - 'I am a string\n' |
615 |
| - 'therefore: I am an error\n') |
| 611 | + # Normally, I would just use tempfile.TemporaryFile(), but here I want |
| 612 | + # to first open the file for writing and then open it for reading. In |
| 613 | + # other words, I need to make sure that the file continues to exist |
| 614 | + # after I close it for the fist time. That’s why I’m using |
| 615 | + # tempfile.TemporaryDirectory() instead of tempfile.TemporaryFile(). |
| 616 | + with tempfile.TemporaryDirectory() as temp_dir_path: |
| 617 | + stdin_file_path = os.path.join(temp_dir_path, 'stdin') |
| 618 | + with open(stdin_file_path, mode='w', encoding='utf_8') as file: |
| 619 | + file.write( |
| 620 | + 'I am a string\n' |
| 621 | + 'therefore: I am an error\n') |
| 622 | + with open(stdin_file_path, mode='r', encoding='utf-8') as file: |
| 623 | + # prepares stdin with an invalid yaml string so that we can |
| 624 | + # check for its specific error, and be assured that stdin was |
| 625 | + # read |
| 626 | + sys.stdin = file |
616 | 627 |
|
617 |
| - with RunContext(self) as ctx: |
618 |
| - cli.run(('-', '-f', 'parsable')) |
619 |
| - expected_out = ( |
620 |
| - 'stdin:2:10: [error] syntax error: ' |
621 |
| - 'mapping values are not allowed here (syntax)\n') |
622 |
| - self.assertEqual( |
623 |
| - (ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, '')) |
| 628 | + with RunContext(self) as ctx: |
| 629 | + cli.run(('-', '-f', 'parsable')) |
| 630 | + expected_out = ( |
| 631 | + 'stdin:2:10: [error] syntax error: ' |
| 632 | + 'mapping values are not allowed here (syntax)\n') |
| 633 | + self.assertEqual( |
| 634 | + (ctx.returncode, ctx.stdout, ctx.stderr), |
| 635 | + (1, expected_out, '')) |
624 | 636 |
|
625 | 637 | def test_run_no_warnings(self):
|
626 | 638 | path = os.path.join(self.wd, 'a.yaml')
|
@@ -817,7 +829,35 @@ def tearDownClass(cls):
|
817 | 829 | super().tearDownClass()
|
818 | 830 | unregister_test_codecs()
|
819 | 831 |
|
| 832 | + def valid_encodings_stdin_test_helper( |
| 833 | + self, |
| 834 | + config_path, |
| 835 | + root_dir, |
| 836 | + old_stdin |
| 837 | + ): |
| 838 | + for path in glob.glob(os.path.join(root_dir, '**')): |
| 839 | + # We purposely choose the wrong text encoding here because the text |
| 840 | + # encoding shouldn’t matter. yamllint should completely ignore the |
| 841 | + # text encoding of stdin. |
| 842 | + with open(path, mode="r", encoding="cp037") as file: |
| 843 | + sys.stdin = file |
| 844 | + with RunContext(self) as ctx: |
| 845 | + cli.run(('-c', config_path, '-')) |
| 846 | + sys.stdin = old_stdin |
| 847 | + if root_dir == 'sorted_correctly': |
| 848 | + self.assertEqual(ctx.returncode, 0) |
| 849 | + elif root_dir == 'sorted_incorrectly': |
| 850 | + self.assertNotEqual(ctx.returncode, 0) |
| 851 | + else: |
| 852 | + raise ValueError( |
| 853 | + f"root_dir was set to {repr(root_dir)}. It should only" |
| 854 | + "ever be set to 'sorted_correctly' or" |
| 855 | + "'sorted_incorrectly'." |
| 856 | + ) |
| 857 | + |
820 | 858 | def test_valid_encodings(self):
|
| 859 | + old_stdin = sys.stdin |
| 860 | + self.addCleanup(setattr, sys, 'stdin', old_stdin) |
821 | 861 | conf = ('---\n'
|
822 | 862 | 'rules:\n'
|
823 | 863 | ' key-ordering: enable\n')
|
@@ -847,9 +887,23 @@ def test_valid_encodings(self):
|
847 | 887 |
|
848 | 888 | with temp_workspace(workspace):
|
849 | 889 | for config_path in config_files.keys():
|
| 890 | + # First, make sure that encoding autodetection works when the |
| 891 | + # file’s path is given as a command-line argument. |
850 | 892 | with RunContext(self) as ctx:
|
851 | 893 | cli.run(('-c', config_path, 'sorted_correctly'))
|
852 | 894 | self.assertEqual(ctx.returncode, 0)
|
853 | 895 | with RunContext(self) as ctx:
|
854 | 896 | cli.run(('-c', config_path, 'sorted_incorrectly'))
|
855 | 897 | self.assertNotEqual(ctx.returncode, 0)
|
| 898 | + # Second, make sure that encoding autodetection works when the |
| 899 | + # file is piped to yamllint via stdin. |
| 900 | + self.valid_encodings_stdin_test_helper( |
| 901 | + config_path, |
| 902 | + 'sorted_correctly', |
| 903 | + old_stdin |
| 904 | + ) |
| 905 | + self.valid_encodings_stdin_test_helper( |
| 906 | + config_path, |
| 907 | + 'sorted_incorrectly', |
| 908 | + old_stdin |
| 909 | + ) |
0 commit comments