8
8
import os
9
9
import sys
10
10
import importlib
11
+ import importlib .abc
12
+ import importlib .util
11
13
import unittest
12
14
import tempfile
15
+ import shutil
16
+ import contextlib
13
17
14
18
# NOTE: There are some additional tests relating to interaction with
15
19
# zipimport in the test_zipimport_support test module.
@@ -437,7 +441,7 @@ def basics(): r"""
437
441
>>> tests = finder.find(sample_func)
438
442
439
443
>>> print(tests) # doctest: +ELLIPSIS
440
- [<DocTest sample_func from ...:21 (1 example)>]
444
+ [<DocTest sample_func from ...:25 (1 example)>]
441
445
442
446
The exact name depends on how test_doctest was invoked, so allow for
443
447
leading path components.
@@ -2663,12 +2667,52 @@ def test_testfile(): r"""
2663
2667
>>> sys.argv = save_argv
2664
2668
"""
2665
2669
2670
+ class TestImporter (importlib .abc .MetaPathFinder , importlib .abc .ResourceLoader ):
2671
+
2672
+ def find_spec (self , fullname , path , target = None ):
2673
+ return importlib .util .spec_from_file_location (fullname , path , loader = self )
2674
+
2675
+ def get_data (self , path ):
2676
+ with open (path , mode = 'rb' ) as f :
2677
+ return f .read ()
2678
+
2679
+ class TestHook :
2680
+
2681
+ def __init__ (self , pathdir ):
2682
+ self .sys_path = sys .path [:]
2683
+ self .meta_path = sys .meta_path [:]
2684
+ self .path_hooks = sys .path_hooks [:]
2685
+ sys .path .append (pathdir )
2686
+ sys .path_importer_cache .clear ()
2687
+ self .modules_before = sys .modules .copy ()
2688
+ self .importer = TestImporter ()
2689
+ sys .meta_path .append (self .importer )
2690
+
2691
+ def remove (self ):
2692
+ sys .path [:] = self .sys_path
2693
+ sys .meta_path [:] = self .meta_path
2694
+ sys .path_hooks [:] = self .path_hooks
2695
+ sys .path_importer_cache .clear ()
2696
+ sys .modules .clear ()
2697
+ sys .modules .update (self .modules_before )
2698
+
2699
+
2700
+ @contextlib .contextmanager
2701
+ def test_hook (pathdir ):
2702
+ hook = TestHook (pathdir )
2703
+ try :
2704
+ yield hook
2705
+ finally :
2706
+ hook .remove ()
2707
+
2708
+
2666
2709
def test_lineendings (): r"""
2667
- *nix systems use \n line endings, while Windows systems use \r\n. Python
2710
+ *nix systems use \n line endings, while Windows systems use \r\n, and
2711
+ old Mac systems used \r, which Python still recognizes as a line ending. Python
2668
2712
handles this using universal newline mode for reading files. Let's make
2669
2713
sure doctest does so (issue 8473) by creating temporary test files using each
2670
- of the two line disciplines. One of the two will be the "wrong" one for the
2671
- platform the test is run on.
2714
+ of the three line disciplines. At least one will not match either the universal
2715
+ newline \n or os.linesep for the platform the test is run on.
2672
2716
2673
2717
Windows line endings first:
2674
2718
@@ -2691,6 +2735,47 @@ def test_lineendings(): r"""
2691
2735
TestResults(failed=0, attempted=1)
2692
2736
>>> os.remove(fn)
2693
2737
2738
+ And finally old Mac line endings:
2739
+
2740
+ >>> fn = tempfile.mktemp()
2741
+ >>> with open(fn, 'wb') as f:
2742
+ ... f.write(b'Test:\r\r >>> x = 1 + 1\r\rDone.\r')
2743
+ 30
2744
+ >>> doctest.testfile(fn, module_relative=False, verbose=False)
2745
+ TestResults(failed=0, attempted=1)
2746
+ >>> os.remove(fn)
2747
+
2748
+ Now we test with a package loader that has a get_data method, since that
2749
+ bypasses the standard universal newline handling so doctest has to do the
2750
+ newline conversion itself; let's make sure it does so correctly (issue 1812).
2751
+ We'll write a file inside the package that has all three kinds of line endings
2752
+ in it, and use a package hook to install a custom loader; on any platform,
2753
+ at least one of the line endings will raise a ValueError for inconsistent
2754
+ whitespace if doctest does not correctly do the newline conversion.
2755
+
2756
+ >>> dn = tempfile.mkdtemp()
2757
+ >>> pkg = os.path.join(dn, "doctest_testpkg")
2758
+ >>> os.mkdir(pkg)
2759
+ >>> support.create_empty_file(os.path.join(pkg, "__init__.py"))
2760
+ >>> fn = os.path.join(pkg, "doctest_testfile.txt")
2761
+ >>> with open(fn, 'wb') as f:
2762
+ ... f.write(
2763
+ ... b'Test:\r\n\r\n'
2764
+ ... b' >>> x = 1 + 1\r\n\r\n'
2765
+ ... b'Done.\r\n'
2766
+ ... b'Test:\n\n'
2767
+ ... b' >>> x = 1 + 1\n\n'
2768
+ ... b'Done.\n'
2769
+ ... b'Test:\r\r'
2770
+ ... b' >>> x = 1 + 1\r\r'
2771
+ ... b'Done.\r'
2772
+ ... )
2773
+ 95
2774
+ >>> with test_hook(dn):
2775
+ ... doctest.testfile("doctest_testfile.txt", package="doctest_testpkg", verbose=False)
2776
+ TestResults(failed=0, attempted=3)
2777
+ >>> shutil.rmtree(dn)
2778
+
2694
2779
"""
2695
2780
2696
2781
def test_testmod (): r"""
0 commit comments