33# pylint: disable=function-redefined, missing-function-docstring, not-callable
44# pyright: reportRedeclaration=false, reportAttributeAccessIssue=false, reportCallIssue=false
55
6+ import contextlib
67import difflib
78import json
89import os
910import pathlib
1011import re
12+ import sys
13+ from io import StringIO
1114from itertools import zip_longest
1215from typing import Iterable , List , Optional , Pattern , Tuple , Union
1316
2831abs_path = re .compile (r"/some/dir" )
2932
3033
31- def make_relative_if_path (
32- some_string : str , base_dir : Union [str , os .PathLike ] = "."
33- ) -> str :
34- """
35- Convert a string to a relative path if it's a path, relative to base_dir.
36- Works even if the path is outside the base_dir.
34+ @contextlib .contextmanager
35+ def tee_stdout ():
36+ """Contextmanager duplicating stdout."""
37+ original_stdout = sys .stdout
38+ buffer = StringIO ()
3739
38- Args:
39- some_string (str): String to check.
40- base_dir (str or Path): Base directory for relative path.
40+ class Tee :
41+ """Tee class for stdout."""
4142
42- Returns :
43- str: Relative path if s is a path, otherwise original string.
44- """
45- the_path = pathlib . Path ( some_string )
43+ def write ( self , data ) :
44+ original_stdout . write ( data )
45+ buffer . write ( data )
46+ original_stdout . flush ( )
4647
47- if not the_path .is_absolute ():
48- return some_string
48+ def flush (self ):
49+ original_stdout .flush ()
50+ buffer .flush ()
4951
52+ sys .stdout = Tee ()
5053 try :
51- return os . path . relpath ( str ( the_path ), base_dir )
52- except ValueError :
53- return some_string
54+ yield buffer
55+ finally :
56+ sys . stdout = original_stdout
5457
5558
5659def remote_server_path (context ):
@@ -61,15 +64,18 @@ def remote_server_path(context):
6164def call_command (context : Context , args : list [str ], path : Optional [str ] = "." ) -> None :
6265 length_at_start = len (context .captured .output )
6366 with in_directory (path or "." ):
64- try :
65- run (args )
66- context .cmd_returncode = 0
67- except DfetchFatalException :
68- context .cmd_returncode = 1
67+ with tee_stdout () as captured_stdout :
68+ try :
69+ run (args )
70+ context .cmd_returncode = 0
71+ except DfetchFatalException :
72+ context .cmd_returncode = 1
6973 # Remove the color code + title
7074 context .cmd_output = dfetch_title .sub (
7175 "" , ansi_escape .sub ("" , context .captured .output [length_at_start :].strip ("\n " ))
7276 )
77+ captured_stdout .seek (0 )
78+ context .cmd_stdout = captured_stdout .read ()
7379
7480
7581def check_file (path , content ):
@@ -110,7 +116,6 @@ def check_content(
110116 (iso_timestamp , "[timestamp]" ),
111117 (urn_uuid , "[urn-uuid]" ),
112118 (bom_ref , "[bom-ref]" ),
113- (abs_path , "." ),
114119 ],
115120 text = expected ,
116121 )
@@ -125,8 +130,6 @@ def check_content(
125130 text = actual ,
126131 )
127132
128- actual = make_relative_if_path (actual )
129-
130133 assert actual .strip () == expected .strip (), (
131134 f"Line { line_nr } : Actual >>{ actual .strip ()} << != Expected >>{ expected .strip ()} <<\n "
132135 f"ACTUAL:\n { '' .join (actual_content )} "
@@ -199,7 +202,6 @@ def step_impl(context, path=None):
199202@when ('I run "dfetch {args}"' )
200203def step_impl (context , args , path = None ):
201204 """Call a command."""
202- context .cmd_output = ""
203205 call_command (context , args .split (), path )
204206
205207
@@ -252,6 +254,7 @@ def step_impl(context):
252254 (timestamp , "[timestamp]" ),
253255 (dfetch_title , "" ),
254256 (svn_error , "svn: EXXXXXX: <some error text>" ),
257+ (abs_path , "" ),
255258 ],
256259 text = context .text ,
257260 )
@@ -266,8 +269,9 @@ def step_impl(context):
266269 "some-remote-server" ,
267270 ),
268271 (svn_error , "svn: EXXXXXX: <some error text>" ),
272+ (re .compile (re .escape (os .getcwd ())), "" ),
269273 ],
270- text = context .cmd_output ,
274+ text = context .cmd_stdout or context . cmd_output ,
271275 )
272276
273277 diff = difflib .ndiff (actual_text .splitlines (), expected_text .splitlines ())
0 commit comments