1717import shlex
1818import subprocess
1919import urllib .parse
20- from typing import TYPE_CHECKING , Any , Optional
20+ from typing import TYPE_CHECKING , Any , Optional , Union
2121
2222if TYPE_CHECKING :
2323 import testinfra .host
@@ -33,6 +33,7 @@ class HostSpec:
3333 password : Optional [str ]
3434
3535
36+ @dataclasses .dataclass
3637class CommandResult :
3738 """Object that encapsulates all returned details of the command execution.
3839
@@ -51,24 +52,11 @@ class CommandResult:
5152 False
5253 """
5354
54- def __init__ (
55- self ,
56- backend : "BaseBackend" ,
57- exit_status : int ,
58- command : bytes ,
59- stdout_bytes : bytes ,
60- stderr_bytes : bytes ,
61- stdout : Optional [str ] = None ,
62- stderr : Optional [str ] = None ,
63- ):
64- self .exit_status = exit_status
65- self ._stdout_bytes = stdout_bytes
66- self ._stderr_bytes = stderr_bytes
67- self ._stdout = stdout
68- self ._stderr = stderr
69- self .command = command
70- self ._backend = backend
71- super ().__init__ ()
55+ backend : "BaseBackend"
56+ exit_status : int
57+ command : bytes
58+ _stdout : Union [str , bytes ]
59+ _stderr : Union [str , bytes ]
7260
7361 @property
7462 def succeeded (self ) -> bool :
@@ -104,8 +92,8 @@ def stdout(self) -> str:
10492 >>> host.run("mkdir -v new_directory").stdout
10593 mkdir: created directory 'new_directory'
10694 """
107- if self ._stdout is None :
108- self . _stdout = self ._backend .decode (self ._stdout_bytes )
95+ if isinstance ( self ._stdout , bytes ) :
96+ return self .backend .decode (self ._stdout )
10997 return self ._stdout
11098
11199 @property
@@ -115,8 +103,8 @@ def stderr(self) -> str:
115103 >>> host.run("mkdir new_directory").stderr
116104 mkdir: cannot create directory 'new_directory': File exists
117105 """
118- if self ._stderr is None :
119- self . _stderr = self ._backend .decode (self ._stderr_bytes )
106+ if isinstance ( self ._stderr , bytes ) :
107+ return self .backend .decode (self ._stderr )
120108 return self ._stderr
121109
122110 @property
@@ -126,9 +114,9 @@ def stdout_bytes(self) -> bytes:
126114 >>> host.run("mkdir -v new_directory").stdout_bytes
127115 b"mkdir: created directory 'new_directory'"
128116 """
129- if self ._stdout_bytes is None :
130- self . _stdout_bytes = self ._backend .encode (self ._stdout )
131- return self ._stdout_bytes
117+ if isinstance ( self ._stdout , str ) :
118+ return self .backend .encode (self ._stdout )
119+ return self ._stdout
132120
133121 @property
134122 def stderr_bytes (self ) -> bytes :
@@ -137,19 +125,9 @@ def stderr_bytes(self) -> bytes:
137125 >>> host.run("mkdir new_directory").stderr_bytes
138126 b"mkdir: cannot create directory 'new_directory': File exists"
139127 """
140- if self ._stderr_bytes is None :
141- self ._stderr_bytes = self ._backend .encode (self ._stderr )
142- return self ._stderr_bytes
143-
144- def __repr__ (self ) -> str :
145- return (
146- "CommandResult(command={!r}, exit_status={}, stdout={!r}, " "stderr={!r})"
147- ).format (
148- self .command ,
149- self .exit_status ,
150- self ._stdout_bytes or self ._stdout ,
151- self ._stderr_bytes or self ._stderr ,
152- )
128+ if isinstance (self ._stderr , str ):
129+ return self .backend .encode (self ._stderr )
130+ return self ._stderr
153131
154132
155133class BaseBackend (metaclass = abc .ABCMeta ):
@@ -337,7 +315,15 @@ def encode(self, data: str) -> bytes:
337315 except UnicodeEncodeError :
338316 return data .encode (self .encoding )
339317
340- def result (self , * args : Any , ** kwargs : Any ) -> CommandResult :
341- result = CommandResult (self , * args , ** kwargs )
318+ def result (
319+ self , rc : int , cmd : bytes , stdout : Union [str , bytes ], stderr : Union [str , bytes ]
320+ ) -> CommandResult :
321+ result = CommandResult (
322+ backend = self ,
323+ exit_status = rc ,
324+ command = cmd ,
325+ _stdout = stdout ,
326+ _stderr = stderr ,
327+ )
342328 logger .debug ("RUN %s" , result )
343329 return result
0 commit comments