17
17
import shlex
18
18
import subprocess
19
19
import urllib .parse
20
- from typing import TYPE_CHECKING , Any , Optional
20
+ from typing import TYPE_CHECKING , Any , Optional , Union
21
21
22
22
if TYPE_CHECKING :
23
23
import testinfra .host
@@ -33,6 +33,7 @@ class HostSpec:
33
33
password : Optional [str ]
34
34
35
35
36
+ @dataclasses .dataclass
36
37
class CommandResult :
37
38
"""Object that encapsulates all returned details of the command execution.
38
39
@@ -51,24 +52,11 @@ class CommandResult:
51
52
False
52
53
"""
53
54
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 ]
72
60
73
61
@property
74
62
def succeeded (self ) -> bool :
@@ -104,8 +92,8 @@ def stdout(self) -> str:
104
92
>>> host.run("mkdir -v new_directory").stdout
105
93
mkdir: created directory 'new_directory'
106
94
"""
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 )
109
97
return self ._stdout
110
98
111
99
@property
@@ -115,8 +103,8 @@ def stderr(self) -> str:
115
103
>>> host.run("mkdir new_directory").stderr
116
104
mkdir: cannot create directory 'new_directory': File exists
117
105
"""
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 )
120
108
return self ._stderr
121
109
122
110
@property
@@ -126,9 +114,9 @@ def stdout_bytes(self) -> bytes:
126
114
>>> host.run("mkdir -v new_directory").stdout_bytes
127
115
b"mkdir: created directory 'new_directory'"
128
116
"""
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
132
120
133
121
@property
134
122
def stderr_bytes (self ) -> bytes :
@@ -137,19 +125,9 @@ def stderr_bytes(self) -> bytes:
137
125
>>> host.run("mkdir new_directory").stderr_bytes
138
126
b"mkdir: cannot create directory 'new_directory': File exists"
139
127
"""
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
153
131
154
132
155
133
class BaseBackend (metaclass = abc .ABCMeta ):
@@ -337,7 +315,15 @@ def encode(self, data: str) -> bytes:
337
315
except UnicodeEncodeError :
338
316
return data .encode (self .encoding )
339
317
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
+ )
342
328
logger .debug ("RUN %s" , result )
343
329
return result
0 commit comments