Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb67ae42

Browse files
Merge branch 'master' into skip-ssl-check
The following files were modified manualy:- testgres/node.py- testgres/operations/local_ops.py- tests/test_remote.py
2 parents67f23a7 +b949eb8 commitb67ae42

11 files changed

+267
-58
lines changed

‎testgres/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
CatchUpException, \
2424
StartNodeException, \
2525
InitNodeException, \
26-
BackupException
26+
BackupException, \
27+
InvalidOperationException
2728

2829
from .enumsimport \
2930
XLogMethod, \
@@ -60,7 +61,7 @@
6061
"NodeBackup","testgres_config",
6162
"TestgresConfig","configure_testgres","scoped_config","push_config","pop_config",
6263
"NodeConnection","DatabaseError","InternalError","ProgrammingError","OperationalError",
63-
"TestgresException","ExecUtilException","QueryException","TimeoutException","CatchUpException","StartNodeException","InitNodeException","BackupException",
64+
"TestgresException","ExecUtilException","QueryException","TimeoutException","CatchUpException","StartNodeException","InitNodeException","BackupException","InvalidOperationException",
6465
"XLogMethod","IsolationLevel","NodeStatus","ProcessType","DumpFormat",
6566
"PostgresNode","NodeApp",
6667
"reserve_port","release_port","bound_ports","get_bin_path","get_pg_config","get_pg_version",

‎testgres/exceptions.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ class TestgresException(Exception):
99

1010
@six.python_2_unicode_compatible
1111
classExecUtilException(TestgresException):
12-
def__init__(self,message=None,command=None,exit_code=0,out=None):
12+
def__init__(self,message=None,command=None,exit_code=0,out=None,error=None):
1313
super(ExecUtilException,self).__init__(message)
1414

1515
self.message=message
1616
self.command=command
1717
self.exit_code=exit_code
1818
self.out=out
19+
self.error=error
1920

2021
def__str__(self):
2122
msg= []
@@ -24,13 +25,17 @@ def __str__(self):
2425
msg.append(self.message)
2526

2627
ifself.command:
27-
msg.append(u'Command: {}'.format(self.command))
28+
command_s=' '.join(self.command)ifisinstance(self.command,list)elseself.command,
29+
msg.append(u'Command: {}'.format(command_s))
2830

2931
ifself.exit_code:
3032
msg.append(u'Exit code: {}'.format(self.exit_code))
3133

34+
ifself.error:
35+
msg.append(u'---- Error:\n{}'.format(self.error))
36+
3237
ifself.out:
33-
msg.append(u'----\n{}'.format(self.out))
38+
msg.append(u'---- Out:\n{}'.format(self.out))
3439

3540
returnself.convert_and_join(msg)
3641

@@ -98,3 +103,7 @@ class InitNodeException(TestgresException):
98103

99104
classBackupException(TestgresException):
100105
pass
106+
107+
108+
classInvalidOperationException(TestgresException):
109+
pass

‎testgres/node.py

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@
7474
TimeoutException, \
7575
InitNodeException, \
7676
TestgresException, \
77-
BackupException
77+
BackupException, \
78+
InvalidOperationException
7879

7980
from .loggerimportTestgresLogger
8081

@@ -1005,6 +1006,37 @@ def psql(self,
10051006
>>> psql(query='select 3', ON_ERROR_STOP=1)
10061007
"""
10071008

1009+
returnself._psql(
1010+
ignore_errors=True,
1011+
query=query,
1012+
filename=filename,
1013+
dbname=dbname,
1014+
username=username,
1015+
input=input,
1016+
**variables
1017+
)
1018+
1019+
def_psql(
1020+
self,
1021+
ignore_errors,
1022+
query=None,
1023+
filename=None,
1024+
dbname=None,
1025+
username=None,
1026+
input=None,
1027+
**variables):
1028+
asserttype(variables)==dict# noqa: E721
1029+
1030+
#
1031+
# We do not support encoding. It may be added later. Ok?
1032+
#
1033+
ifinputisNone:
1034+
pass
1035+
eliftype(input)==bytes:# noqa: E721
1036+
pass
1037+
else:
1038+
raiseException("Input data must be None or bytes.")
1039+
10081040
dbname=dbnameordefault_dbname()
10091041

10101042
psql_params= [
@@ -1035,20 +1067,14 @@ def psql(self,
10351067

10361068
# should be the last one
10371069
psql_params.append(dbname)
1038-
ifnotself.os_ops.conn_params.remote:
1039-
# start psql process
1040-
process=subprocess.Popen(psql_params,
1041-
stdin=subprocess.PIPE,
1042-
stdout=subprocess.PIPE,
1043-
stderr=subprocess.PIPE)
1044-
1045-
# wait until it finishes and get stdout and stderr
1046-
out,err=process.communicate(input=input)
1047-
returnprocess.returncode,out,err
1048-
else:
1049-
status_code,out,err=self.os_ops.exec_command(psql_params,verbose=True,input=input)
10501070

1051-
returnstatus_code,out,err
1071+
returnself.os_ops.exec_command(
1072+
psql_params,
1073+
verbose=True,
1074+
input=input,
1075+
stderr=subprocess.PIPE,
1076+
stdout=subprocess.PIPE,
1077+
ignore_errors=ignore_errors)
10521078

10531079
@method_decorator(positional_args_hack(['dbname','query']))
10541080
defsafe_psql(self,query=None,expect_error=False,**kwargs):
@@ -1069,22 +1095,27 @@ def safe_psql(self, query=None, expect_error=False, **kwargs):
10691095
Returns:
10701096
psql's output as str.
10711097
"""
1098+
asserttype(kwargs)==dict# noqa: E721
1099+
assertnot ("ignore_errors"inkwargs.keys())
1100+
assertnot ("expect_error"inkwargs.keys())
10721101

10731102
# force this setting
10741103
kwargs['ON_ERROR_STOP']=1
10751104
try:
1076-
ret,out,err=self.psql(query=query,**kwargs)
1105+
ret,out,err=self._psql(ignore_errors=False,query=query,**kwargs)
10771106
exceptExecUtilExceptionase:
1078-
ret=e.exit_code
1079-
out=e.out
1080-
err=e.message
1081-
ifret:
1082-
ifexpect_error:
1083-
out= (errorb'').decode('utf-8')
1084-
else:
1085-
raiseQueryException((errorb'').decode('utf-8'),query)
1086-
elifexpect_error:
1087-
assertFalse,"Exception was expected, but query finished successfully: `{}` ".format(query)
1107+
ifnotexpect_error:
1108+
raiseQueryException(e.message,query)
1109+
1110+
iftype(e.error)==bytes:# noqa: E721
1111+
returne.error.decode("utf-8")# throw
1112+
1113+
# [2024-12-09] This situation is not expected
1114+
assertFalse
1115+
returne.error
1116+
1117+
ifexpect_error:
1118+
raiseInvalidOperationException("Exception was expected, but query finished successfully: `{}`.".format(query))
10881119

10891120
returnout
10901121

‎testgres/operations/helpers.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
importlocale
2+
3+
4+
classHelpers:
5+
def_make_get_default_encoding_func():
6+
# locale.getencoding is added in Python 3.11
7+
ifhasattr(locale,'getencoding'):
8+
returnlocale.getencoding
9+
10+
# It must exist
11+
returnlocale.getpreferredencoding
12+
13+
# Prepared pointer on function to get a name of system codepage
14+
_get_default_encoding_func=_make_get_default_encoding_func()
15+
16+
defGetDefaultEncoding():
17+
#
18+
# Original idea/source was:
19+
#
20+
# def os_ops.get_default_encoding():
21+
# if not hasattr(locale, 'getencoding'):
22+
# locale.getencoding = locale.getpreferredencoding
23+
# return locale.getencoding() or 'UTF-8'
24+
#
25+
26+
assert__class__._get_default_encoding_funcisnotNone
27+
28+
r=__class__._get_default_encoding_func()
29+
30+
ifr:
31+
assertrisnotNone
32+
asserttype(r)==str# noqa: E721
33+
assertr!=""
34+
returnr
35+
36+
# Is it an unexpected situation?
37+
return'UTF-8'
38+
39+
defPrepareProcessInput(input,encoding):
40+
ifnotinput:
41+
returnNone
42+
43+
iftype(input)==str:# noqa: E721
44+
ifencodingisNone:
45+
returninput.encode(__class__.GetDefaultEncoding())
46+
47+
asserttype(encoding)==str# noqa: E721
48+
returninput.encode(encoding)
49+
50+
# It is expected!
51+
asserttype(input)==bytes# noqa: E721
52+
returninput

‎testgres/operations/local_ops.py

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
from ..exceptionsimportExecUtilException
1212
from .os_opsimportConnectionParams,OsOperations,get_default_encoding
13+
from .raise_errorimportRaiseError
14+
from .helpersimportHelpers
1315

1416
try:
1517
fromshutilimportwhichasfind_executable
@@ -41,14 +43,6 @@ def __init__(self, conn_params=None):
4143
conn_params=ConnectionParams()
4244
super(LocalOperations,self).__init__(conn_params)
4345

44-
@staticmethod
45-
def_raise_exec_exception(message,command,exit_code,output):
46-
"""Raise an ExecUtilException."""
47-
raiseExecUtilException(message=message.format(output),
48-
command=' '.join(command)ifisinstance(command,list)elsecommand,
49-
exit_code=exit_code,
50-
out=output)
51-
5246
@staticmethod
5347
def_process_output(encoding,temp_file_path):
5448
"""Process the output of a command from a temporary file."""
@@ -59,6 +53,8 @@ def _process_output(encoding, temp_file_path):
5953
returnoutput,None# In Windows stderr writing in stdout
6054

6155
def_run_command__nt(self,cmd,shell,input,stdin,stdout,stderr,get_process,timeout,encoding):
56+
# TODO: why don't we use the data from input?
57+
6258
withtempfile.NamedTemporaryFile(mode='w+b',delete=False)astemp_file:
6359
stdout=temp_file
6460
stderr=subprocess.STDOUT
@@ -80,25 +76,36 @@ def _run_command__nt(self, cmd, shell, input, stdin, stdout, stderr, get_process
8076
returnprocess,output,error
8177

8278
def_run_command__generic(self,cmd,shell,input,stdin,stdout,stderr,get_process,timeout,encoding):
79+
input_prepared=None
80+
ifnotget_process:
81+
input_prepared=Helpers.PrepareProcessInput(input,encoding)# throw
82+
83+
assertinput_preparedisNoneor (type(input_prepared)==bytes)# noqa: E721
84+
8385
process=subprocess.Popen(
8486
cmd,
8587
shell=shell,
8688
stdin=stdinorsubprocess.PIPEifinputisnotNoneelseNone,
8789
stdout=stdoutorsubprocess.PIPE,
8890
stderr=stderrorsubprocess.PIPE,
8991
)
92+
assertnot (processisNone)
9093
ifget_process:
9194
returnprocess,None,None
9295
try:
93-
output,error=process.communicate(input=input.encode(encoding)ifinputelseNone,timeout=timeout)
94-
ifencoding:
95-
output=output.decode(encoding)
96-
error=error.decode(encoding)
97-
returnprocess,output,error
96+
output,error=process.communicate(input=input_prepared,timeout=timeout)
9897
exceptsubprocess.TimeoutExpired:
9998
process.kill()
10099
raiseExecUtilException("Command timed out after {} seconds.".format(timeout))
101100

101+
asserttype(output)==bytes# noqa: E721
102+
asserttype(error)==bytes# noqa: E721
103+
104+
ifencoding:
105+
output=output.decode(encoding)
106+
error=error.decode(encoding)
107+
returnprocess,output,error
108+
102109
def_run_command(self,cmd,shell,input,stdin,stdout,stderr,get_process,timeout,encoding):
103110
"""Execute a command and return the process and its output."""
104111
ifos.name=='nt'andstdoutisNone:# Windows
@@ -114,11 +121,20 @@ def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False,
114121
"""
115122
Execute a command in a subprocess and handle the output based on the provided parameters.
116123
"""
124+
asserttype(expect_error)==bool# noqa: E721
125+
asserttype(ignore_errors)==bool# noqa: E721
126+
117127
process,output,error=self._run_command(cmd,shell,input,stdin,stdout,stderr,get_process,timeout,encoding)
118128
ifget_process:
119129
returnprocess
120130
ifnotignore_errorsand ((process.returncode!=0orhas_errors(output=output,error=error))andnotexpect_error):
121-
self._raise_exec_exception('Utility exited with non-zero code. Error `{}`',cmd,process.returncode,errororoutput)
131+
RaiseError.UtilityExitedWithNonZeroCode(
132+
cmd=cmd,
133+
exit_code=process.returncode,
134+
msg_arg=errororoutput,
135+
error=error,
136+
out=output
137+
)
122138

123139
ifverbose:
124140
returnprocess.returncode,output,error

‎testgres/operations/raise_error.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from ..exceptionsimportExecUtilException
2+
from .helpersimportHelpers
3+
4+
5+
classRaiseError:
6+
defUtilityExitedWithNonZeroCode(cmd,exit_code,msg_arg,error,out):
7+
asserttype(exit_code)==int# noqa: E721
8+
9+
msg_arg_s=__class__._TranslateDataIntoString(msg_arg).strip()
10+
asserttype(msg_arg_s)==str# noqa: E721
11+
12+
ifmsg_arg_s=="":
13+
msg_arg_s="#no_error_message"
14+
15+
message="Utility exited with non-zero code. Error: `"+msg_arg_s+"`"
16+
raiseExecUtilException(
17+
message=message,
18+
command=cmd,
19+
exit_code=exit_code,
20+
out=out,
21+
error=error)
22+
23+
def_TranslateDataIntoString(data):
24+
iftype(data)==bytes:# noqa: E721
25+
return__class__._TranslateDataIntoString__FromBinary(data)
26+
27+
returnstr(data)
28+
29+
def_TranslateDataIntoString__FromBinary(data):
30+
asserttype(data)==bytes# noqa: E721
31+
32+
try:
33+
returndata.decode(Helpers.GetDefaultEncoding())
34+
exceptUnicodeDecodeError:
35+
pass
36+
37+
return"#cannot_decode_text"
38+
39+
def_BinaryIsASCII(data):
40+
asserttype(data)==bytes# noqa: E721
41+
42+
forbindata:
43+
ifnot (b>=0andb<=127):
44+
returnFalse
45+
46+
returnTrue

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp