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

Commitedb5708

Browse files
author
vshepard
committed
Fix initdb error on Windows
1 parent846c05f commitedb5708

File tree

6 files changed

+184
-51
lines changed

6 files changed

+184
-51
lines changed

‎setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@
2727
readme=f.read()
2828

2929
setup(
30-
version='1.9.2',
30+
version='1.9.3',
3131
name='testgres',
3232
packages=['testgres','testgres.operations'],
3333
description='Testing utility for PostgreSQL and its extensions',
3434
url='https://github.com/postgrespro/testgres',
3535
long_description=readme,
3636
long_description_content_type='text/markdown',
3737
license='PostgreSQL',
38-
author='Ildar Musin',
39-
author_email='zildermann@gmail.com',
38+
author='Postgres Professional',
39+
author_email='testgres@postgrespro.ru',
4040
keywords=['test','testing','postgresql'],
4141
install_requires=install_requires,
4242
classifiers=[],

‎testgres/operations/local_ops.py

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
importpsutil
99

1010
from ..exceptionsimportExecUtilException
11-
from .os_opsimportConnectionParams,OsOperations
12-
from .os_opsimportpglib
11+
from .os_opsimportConnectionParams,OsOperations,pglib,get_default_encoding
1312

1413
try:
1514
fromshutilimportwhichasfind_executable
@@ -22,6 +21,12 @@
2221
error_markers= [b'error',b'Permission denied',b'fatal']
2322

2423

24+
defhas_errors(output):
25+
ifisinstance(output,str):
26+
output=output.encode(get_default_encoding())
27+
returnany(markerinoutputformarkerinerror_markers)
28+
29+
2530
classLocalOperations(OsOperations):
2631
def__init__(self,conn_params=None):
2732
ifconn_paramsisNone:
@@ -33,7 +38,38 @@ def __init__(self, conn_params=None):
3338
self.remote=False
3439
self.username=conn_params.usernameorself.get_user()
3540

36-
# Command execution
41+
@staticmethod
42+
def_run_command(cmd,shell,input,timeout,encoding,temp_file=None):
43+
"""Execute a command and return the process."""
44+
iftemp_fileisnotNone:
45+
stdout=temp_file
46+
stderr=subprocess.STDOUT
47+
else:
48+
stdout=subprocess.PIPE
49+
stderr=subprocess.PIPE
50+
51+
process=subprocess.Popen(
52+
cmd,
53+
shell=shell,
54+
stdin=subprocess.PIPEifinputisnotNoneelseNone,
55+
stdout=stdout,
56+
stderr=stderr,
57+
)
58+
59+
try:
60+
returnprocess.communicate(input=input.encode(encoding)ifinputelseNone,timeout=timeout),process
61+
exceptsubprocess.TimeoutExpired:
62+
process.kill()
63+
raiseExecUtilException("Command timed out after {} seconds.".format(timeout))
64+
65+
@staticmethod
66+
def_raise_exec_exception(message,command,exit_code,output):
67+
"""Raise an ExecUtilException."""
68+
raiseExecUtilException(message=message.format(output),
69+
command=command,
70+
exit_code=exit_code,
71+
out=output)
72+
3773
defexec_command(self,cmd,wait_exit=False,verbose=False,
3874
expect_error=False,encoding=None,shell=False,text=False,
3975
input=None,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
@@ -56,16 +92,15 @@ def exec_command(self, cmd, wait_exit=False, verbose=False,
5692
:return: The output of the subprocess.
5793
"""
5894
ifos.name=='nt':
59-
withtempfile.NamedTemporaryFile()asbuf:
60-
process=subprocess.Popen(cmd,stdout=buf,stderr=subprocess.STDOUT)
61-
process.communicate()
62-
buf.seek(0)
63-
result=buf.read().decode(encoding)
64-
returnresult
95+
returnself._exec_command_windows(cmd,wait_exit=wait_exit,verbose=verbose,
96+
expect_error=expect_error,encoding=encoding,shell=shell,text=text,
97+
input=input,stdin=stdin,stdout=stdout,stderr=stderr,
98+
get_process=get_process,timeout=timeout)
6599
else:
66100
process=subprocess.Popen(
67101
cmd,
68102
shell=shell,
103+
stdin=stdin,
69104
stdout=stdout,
70105
stderr=stderr,
71106
)
@@ -79,7 +114,7 @@ def exec_command(self, cmd, wait_exit=False, verbose=False,
79114
raiseExecUtilException("Command timed out after {} seconds.".format(timeout))
80115
exit_status=process.returncode
81116

82-
error_found=exit_status!=0orany(markerinerrorformarkerinerror_markers)
117+
error_found=exit_status!=0orhas_errors(error)
83118

84119
ifencoding:
85120
result=result.decode(encoding)
@@ -91,15 +126,50 @@ def exec_command(self, cmd, wait_exit=False, verbose=False,
91126
ifexit_status!=0orerror_found:
92127
ifexit_status==0:
93128
exit_status=1
94-
raiseExecUtilException(message='Utility exited with non-zero code. Error `{}`'.format(error),
95-
command=cmd,
96-
exit_code=exit_status,
97-
out=result)
129+
self._raise_exec_exception('Utility exited with non-zero code. Error `{}`',cmd,exit_status,result)
98130
ifverbose:
99131
returnexit_status,result,error
100132
else:
101133
returnresult
102134

135+
@staticmethod
136+
def_process_output(process,encoding,temp_file=None):
137+
"""Process the output of a command."""
138+
iftemp_fileisnotNone:
139+
temp_file.seek(0)
140+
output=temp_file.read()
141+
else:
142+
output=process.stdout.read()
143+
144+
ifencoding:
145+
output=output.decode(encoding)
146+
147+
returnoutput
148+
149+
def_exec_command_windows(self,cmd,wait_exit=False,verbose=False,
150+
expect_error=False,encoding=None,shell=False,text=False,
151+
input=None,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,
152+
get_process=None,timeout=None):
153+
withtempfile.NamedTemporaryFile(mode='w+b')astemp_file:
154+
_,process=self._run_command(cmd,shell,input,timeout,encoding,temp_file)
155+
ifget_process:
156+
returnprocess
157+
output=self._process_output(process,encoding,temp_file)
158+
159+
ifprocess.returncode!=0orhas_errors(output):
160+
ifprocess.returncode==0:
161+
process.returncode=1
162+
ifexpect_error:
163+
ifverbose:
164+
returnprocess.returncode,output,output
165+
else:
166+
returnoutput
167+
else:
168+
self._raise_exec_exception('Utility exited with non-zero code. Error `{}`',cmd,process.returncode,
169+
output)
170+
171+
return (process.returncode,output,output)ifverboseelseoutput
172+
103173
# Environment setup
104174
defenviron(self,var_name):
105175
returnos.environ.get(var_name)
@@ -210,7 +280,7 @@ def read(self, filename, encoding=None, binary=False):
210280
ifbinary:
211281
returncontent
212282
ifisinstance(content,bytes):
213-
returncontent.decode(encodingor'utf-8')
283+
returncontent.decode(encodingorget_default_encoding())
214284
returncontent
215285

216286
defreadlines(self,filename,num_lines=0,binary=False,encoding=None):

‎testgres/operations/os_ops.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
importlocale
2+
13
try:
24
importpsycopg2aspglib# noqa: F401
35
exceptImportError:
@@ -14,6 +16,10 @@ def __init__(self, host='127.0.0.1', ssh_key=None, username=None):
1416
self.username=username
1517

1618

19+
defget_default_encoding():
20+
returnlocale.getdefaultlocale()[1]or'UTF-8'
21+
22+
1723
classOsOperations:
1824
def__init__(self,username=None):
1925
self.ssh_key=None

‎testgres/operations/remote_ops.py

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
importlocale
21
importlogging
32
importos
43
importsubprocess
@@ -15,12 +14,7 @@
1514
raiseImportError("You must have psycopg2 or pg8000 modules installed")
1615

1716
from ..exceptionsimportExecUtilException
18-
19-
from .os_opsimportOsOperations,ConnectionParams
20-
21-
ConsoleEncoding=locale.getdefaultlocale()[1]
22-
ifnotConsoleEncoding:
23-
ConsoleEncoding='UTF-8'
17+
from .os_opsimportOsOperations,ConnectionParams,get_default_encoding
2418

2519
error_markers= [b'error',b'Permission denied',b'fatal',b'No such file or directory']
2620

@@ -36,7 +30,7 @@ def kill(self):
3630

3731
defcmdline(self):
3832
command="ps -p {} -o cmd --no-headers".format(self.pid)
39-
stdin,stdout,stderr=self.ssh.exec_command(command,verbose=True,encoding=ConsoleEncoding)
33+
stdin,stdout,stderr=self.ssh.exec_command(command,verbose=True,encoding=get_default_encoding())
4034
cmdline=stdout.strip()
4135
returncmdline.split()
4236

@@ -145,7 +139,7 @@ def environ(self, var_name: str) -> str:
145139
- var_name (str): The name of the environment variable.
146140
"""
147141
cmd="echo ${}".format(var_name)
148-
returnself.exec_command(cmd,encoding=ConsoleEncoding).strip()
142+
returnself.exec_command(cmd,encoding=get_default_encoding()).strip()
149143

150144
deffind_executable(self,executable):
151145
search_paths=self.environ("PATH")
@@ -176,11 +170,11 @@ def set_env(self, var_name: str, var_val: str):
176170

177171
# Get environment variables
178172
defget_user(self):
179-
returnself.exec_command("echo $USER",encoding=ConsoleEncoding).strip()
173+
returnself.exec_command("echo $USER",encoding=get_default_encoding()).strip()
180174

181175
defget_name(self):
182176
cmd='python3 -c "import os; print(os.name)"'
183-
returnself.exec_command(cmd,encoding=ConsoleEncoding).strip()
177+
returnself.exec_command(cmd,encoding=get_default_encoding()).strip()
184178

185179
# Work with dirs
186180
defmakedirs(self,path,remove_existing=False):
@@ -227,7 +221,7 @@ def listdir(self, path):
227221
returnresult.splitlines()
228222

229223
defpath_exists(self,path):
230-
result=self.exec_command("test -e {}; echo $?".format(path),encoding=ConsoleEncoding)
224+
result=self.exec_command("test -e {}; echo $?".format(path),encoding=get_default_encoding())
231225
returnint(result.strip())==0
232226

233227
@property
@@ -264,9 +258,9 @@ def mkdtemp(self, prefix=None):
264258

265259
defmkstemp(self,prefix=None):
266260
ifprefix:
267-
temp_dir=self.exec_command("mktemp {}XXXXX".format(prefix),encoding=ConsoleEncoding)
261+
temp_dir=self.exec_command("mktemp {}XXXXX".format(prefix),encoding=get_default_encoding())
268262
else:
269-
temp_dir=self.exec_command("mktemp",encoding=ConsoleEncoding)
263+
temp_dir=self.exec_command("mktemp",encoding=get_default_encoding())
270264

271265
iftemp_dir:
272266
ifnotos.path.isabs(temp_dir):
@@ -283,7 +277,9 @@ def copytree(self, src, dst):
283277
returnself.exec_command("cp -r {} {}".format(src,dst))
284278

285279
# Work with files
286-
defwrite(self,filename,data,truncate=False,binary=False,read_and_write=False,encoding=ConsoleEncoding):
280+
defwrite(self,filename,data,truncate=False,binary=False,read_and_write=False,encoding=None):
281+
ifnotencoding:
282+
encoding=get_default_encoding()
287283
mode="wb"ifbinaryelse"w"
288284
ifnottruncate:
289285
mode="ab"ifbinaryelse"a"
@@ -302,7 +298,7 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
302298
data=data.encode(encoding)
303299

304300
ifisinstance(data,list):
305-
data= [(sifisinstance(s,str)elses.decode(ConsoleEncoding)).rstrip('\n')+'\n'forsindata]
301+
data= [(sifisinstance(s,str)elses.decode(get_default_encoding())).rstrip('\n')+'\n'forsindata]
306302
tmp_file.writelines(data)
307303
else:
308304
tmp_file.write(data)
@@ -334,7 +330,7 @@ def read(self, filename, binary=False, encoding=None):
334330
result=self.exec_command(cmd,encoding=encoding)
335331

336332
ifnotbinaryandresult:
337-
result=result.decode(encodingorConsoleEncoding)
333+
result=result.decode(encodingorget_default_encoding())
338334

339335
returnresult
340336

@@ -347,7 +343,7 @@ def readlines(self, filename, num_lines=0, binary=False, encoding=None):
347343
result=self.exec_command(cmd,encoding=encoding)
348344

349345
ifnotbinaryandresult:
350-
lines=result.decode(encodingorConsoleEncoding).splitlines()
346+
lines=result.decode(encodingorget_default_encoding()).splitlines()
351347
else:
352348
lines=result.splitlines()
353349

@@ -375,7 +371,7 @@ def kill(self, pid, signal):
375371

376372
defget_pid(self):
377373
# Get current process id
378-
returnint(self.exec_command("echo $$",encoding=ConsoleEncoding))
374+
returnint(self.exec_command("echo $$",encoding=get_default_encoding()))
379375

380376
defget_process_children(self,pid):
381377
command= ["ssh","-i",self.ssh_key,f"{self.username}@{self.host}",f"pgrep -P{pid}"]

‎testgres/utils.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
from __future__importprint_function
55

66
importos
7-
importport_for
7+
importrandom
8+
importsocket
9+
810
importsys
911

1012
fromcontextlibimportcontextmanager
1113
frompackaging.versionimportVersion,InvalidVersion
1214
importre
1315

16+
fromport_forimportPortForException
1417
fromsiximportiteritems
1518

1619
from .exceptionsimportExecUtilException
@@ -37,13 +40,49 @@ def reserve_port():
3740
"""
3841
Generate a new port and add it to 'bound_ports'.
3942
"""
40-
41-
port=port_for.select_random(exclude_ports=bound_ports)
43+
port=select_random(exclude_ports=bound_ports)
4244
bound_ports.add(port)
4345

4446
returnport
4547

4648

49+
defselect_random(
50+
ports=None,
51+
exclude_ports=None,
52+
)->int:
53+
"""
54+
Return random unused port number.
55+
Standard function from port_for does not work on Windows because of error
56+
'port_for.exceptions.PortForException: Can't select a port'
57+
We should update it.
58+
"""
59+
ifportsisNone:
60+
ports=set(range(1024,65535))
61+
62+
ifexclude_portsisNone:
63+
exclude_ports=set()
64+
65+
ports.difference_update(set(exclude_ports))
66+
67+
sampled_ports=random.sample(tuple(ports),min(len(ports),100))
68+
69+
forportinsampled_ports:
70+
ifis_port_free(port):
71+
returnport
72+
73+
raisePortForException("Can't select a port")
74+
75+
76+
defis_port_free(port:int)->bool:
77+
"""Check if a port is free to use."""
78+
withsocket.socket(socket.AF_INET,socket.SOCK_STREAM)ass:
79+
try:
80+
s.bind(("",port))
81+
returnTrue
82+
exceptOSError:
83+
returnFalse
84+
85+
4786
defrelease_port(port):
4887
"""
4988
Free port provided by reserve_port().
@@ -80,7 +119,8 @@ def execute_utility(args, logfile=None, verbose=False):
80119
lines= [u'\n']+ ['# '+lineforlineinout.splitlines()]+ [u'\n']
81120
tconf.os_ops.write(filename=logfile,data=lines)
82121
exceptIOError:
83-
raiseExecUtilException("Problem with writing to logfile `{}` during run command `{}`".format(logfile,args))
122+
raiseExecUtilException(
123+
"Problem with writing to logfile `{}` during run command `{}`".format(logfile,args))
84124
ifverbose:
85125
returnexit_status,out,error
86126
else:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp