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 )} "
@@ -228,7 +231,6 @@ def step_impl(context, path=None):
228231@when ('I run "dfetch {args}"' )
229232def step_impl (context , args , path = None ):
230233 """Call a command."""
231- context .cmd_output = ""
232234 call_command (context , args .split (), path )
233235
234236
@@ -285,6 +287,7 @@ def step_impl(context):
285287 (timestamp , "[timestamp]" ),
286288 (dfetch_title , "" ),
287289 (svn_error , "svn: EXXXXXX: <some error text>" ),
290+ (abs_path , "" ),
288291 ],
289292 text = context .text ,
290293 )
@@ -299,8 +302,9 @@ def step_impl(context):
299302 "some-remote-server" ,
300303 ),
301304 (svn_error , "svn: EXXXXXX: <some error text>" ),
305+ (re .compile (re .escape (os .getcwd ())), "" ),
302306 ],
303- text = context .cmd_output ,
307+ text = context .cmd_stdout or context . cmd_output ,
304308 )
305309
306310 diff = difflib .ndiff (actual_text .splitlines (), expected_text .splitlines ())
0 commit comments