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

Commitddcaea0

Browse files
os_ops::rmdirs (local, remote) was refactored (#207)
* os_ops::rmdirs (local, remote) was refactoredLocalOperations::rmdirs - parameter 'retries' was remaned with 'attempts' - if ignore_errors we raise an errorRemoteOperations::rmdirs - parameter 'verbose' was removed - method returns bool - we prevent to delete a file* [TestRemoteOperations] New tests for rmdirs are added.* test_pg_ctl_wait_option (local, remote) is corrected
1 parent3a1d08b commitddcaea0

File tree

5 files changed

+255
-50
lines changed

5 files changed

+255
-50
lines changed

‎testgres/operations/local_ops.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ def makedirs(self, path, remove_existing=False):
174174
exceptFileExistsError:
175175
pass
176176

177-
defrmdirs(self,path,ignore_errors=True,retries=3,delay=1):
177+
# [2025-02-03] Old name of parameter attempts is "retries".
178+
defrmdirs(self,path,ignore_errors=True,attempts=3,delay=1):
178179
"""
179180
Removes a directory and its contents, retrying on failure.
180181
@@ -183,18 +184,38 @@ def rmdirs(self, path, ignore_errors=True, retries=3, delay=1):
183184
:param retries: Number of attempts to remove the directory.
184185
:param delay: Delay between attempts in seconds.
185186
"""
186-
forattemptinrange(retries):
187+
asserttype(path)==str# noqa: E721
188+
asserttype(ignore_errors)==bool# noqa: E721
189+
asserttype(attempts)==int# noqa: E721
190+
asserttype(delay)==intortype(delay)==float# noqa: E721
191+
assertattempts>0
192+
assertdelay>=0
193+
194+
attempt=0
195+
whileTrue:
196+
assertattempt<attempts
197+
attempt+=1
187198
try:
188-
rmtree(path,ignore_errors=ignore_errors)
189-
ifnotos.path.exists(path):
190-
returnTrue
199+
rmtree(path)
191200
exceptFileNotFoundError:
192-
returnTrue
201+
pass
193202
exceptExceptionase:
194-
logging.error(f"Error: Failed to remove directory{path} on attempt{attempt+1}:{e}")
195-
time.sleep(delay)
196-
logging.error(f"Error: Failed to remove directory{path} after{retries} attempts.")
197-
returnFalse
203+
ifattempt<attempt:
204+
errMsg="Failed to remove directory {0} on attempt {1} ({2}): {3}".format(
205+
path,attempt,type(e).__name__,e
206+
)
207+
logging.warning(errMsg)
208+
time.sleep(delay)
209+
continue
210+
211+
assertattempt==attempts
212+
ifnotignore_errors:
213+
raise
214+
215+
returnFalse
216+
217+
# OK!
218+
returnTrue
198219

199220
deflistdir(self,path):
200221
returnos.listdir(path)

‎testgres/operations/remote_ops.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
importsubprocess
55
importtempfile
66
importio
7+
importlogging
78

89
# we support both pg8000 and psycopg2
910
try:
@@ -222,20 +223,45 @@ def makedirs(self, path, remove_existing=False):
222223
raiseException("Couldn't create dir {} because of error {}".format(path,error))
223224
returnresult
224225

225-
defrmdirs(self,path,verbose=False,ignore_errors=True):
226+
defrmdirs(self,path,ignore_errors=True):
226227
"""
227228
Remove a directory in the remote server.
228229
Args:
229230
- path (str): The path to the directory to be removed.
230-
- verbose (bool): If True, return exit status, result, and error.
231231
- ignore_errors (bool): If True, do not raise error if directory does not exist.
232232
"""
233-
cmd="rm -rf {}".format(path)
234-
exit_status,result,error=self.exec_command(cmd,verbose=True)
235-
ifverbose:
236-
returnexit_status,result,error
237-
else:
238-
returnresult
233+
asserttype(path)==str# noqa: E721
234+
asserttype(ignore_errors)==bool# noqa: E721
235+
236+
# ENOENT = 2 - No such file or directory
237+
# ENOTDIR = 20 - Not a directory
238+
239+
cmd1= [
240+
"if","[","-d",path,"]",";",
241+
"then","rm","-rf",path,";",
242+
"elif","[","-e",path,"]",";",
243+
"then","{","echo","cannot remove '"+path+"': it is not a directory",">&2",";","exit","20",";","}",";",
244+
"else","{","echo","directory '"+path+"' does not exist",">&2",";","exit","2",";","}",";",
245+
"fi"
246+
]
247+
248+
cmd2= ["sh","-c",subprocess.list2cmdline(cmd1)]
249+
250+
try:
251+
self.exec_command(cmd2,encoding=Helpers.GetDefaultEncoding())
252+
exceptExecUtilExceptionase:
253+
ife.exit_code==2:# No such file or directory
254+
returnTrue
255+
256+
ifnotignore_errors:
257+
raise
258+
259+
errMsg="Failed to remove directory {0} ({1}): {2}".format(
260+
path,type(e).__name__,e
261+
)
262+
logging.warning(errMsg)
263+
returnFalse
264+
returnTrue
239265

240266
deflistdir(self,path):
241267
"""

‎tests/test_remote.py

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ def test_makedirs_and_rmdirs_success(self):
9999
assertnotos.path.exists(path)
100100
assertnotself.operations.path_exists(path)
101101

102-
deftest_makedirs_and_rmdirs_failure(self):
102+
deftest_makedirs_failure(self):
103103
"""
104-
Test makedirsand rmdirsfor directory creation and removal failure.
104+
Test makedirs for failure.
105105
"""
106106
# Try to create a directory in a read-only location
107107
path="/root/test_dir"
@@ -110,16 +110,84 @@ def test_makedirs_and_rmdirs_failure(self):
110110
withpytest.raises(Exception):
111111
self.operations.makedirs(path)
112112

113-
# Test rmdirs
114-
whileTrue:
115-
try:
116-
self.operations.rmdirs(path,verbose=True)
117-
exceptExecUtilExceptionase:
118-
asserte.message=="Utility exited with non-zero code (1). Error: `rm: cannot remove '/root/test_dir': Permission denied`"
119-
asserttype(e.error)==bytes# noqa: E721
120-
asserte.error.strip()==b"rm: cannot remove '/root/test_dir': Permission denied"
121-
break
122-
raiseException("We wait an exception!")
113+
deftest_rmdirs(self):
114+
path=self.operations.mkdtemp()
115+
assertos.path.exists(path)
116+
117+
assertself.operations.rmdirs(path,ignore_errors=False)isTrue
118+
assertnotos.path.exists(path)
119+
120+
deftest_rmdirs__01_with_subfolder(self):
121+
# folder with subfolder
122+
path=self.operations.mkdtemp()
123+
assertos.path.exists(path)
124+
125+
dir1=os.path.join(path,"dir1")
126+
assertnotos.path.exists(dir1)
127+
128+
self.operations.makedirs(dir1)
129+
assertos.path.exists(dir1)
130+
131+
assertself.operations.rmdirs(path,ignore_errors=False)isTrue
132+
assertnotos.path.exists(path)
133+
assertnotos.path.exists(dir1)
134+
135+
deftest_rmdirs__02_with_file(self):
136+
# folder with file
137+
path=self.operations.mkdtemp()
138+
assertos.path.exists(path)
139+
140+
file1=os.path.join(path,"file1.txt")
141+
assertnotos.path.exists(file1)
142+
143+
self.operations.touch(file1)
144+
assertos.path.exists(file1)
145+
146+
assertself.operations.rmdirs(path,ignore_errors=False)isTrue
147+
assertnotos.path.exists(path)
148+
assertnotos.path.exists(file1)
149+
150+
deftest_rmdirs__03_with_subfolder_and_file(self):
151+
# folder with subfolder and file
152+
path=self.operations.mkdtemp()
153+
assertos.path.exists(path)
154+
155+
dir1=os.path.join(path,"dir1")
156+
assertnotos.path.exists(dir1)
157+
158+
self.operations.makedirs(dir1)
159+
assertos.path.exists(dir1)
160+
161+
file1=os.path.join(dir1,"file1.txt")
162+
assertnotos.path.exists(file1)
163+
164+
self.operations.touch(file1)
165+
assertos.path.exists(file1)
166+
167+
assertself.operations.rmdirs(path,ignore_errors=False)isTrue
168+
assertnotos.path.exists(path)
169+
assertnotos.path.exists(dir1)
170+
assertnotos.path.exists(file1)
171+
172+
deftest_rmdirs__try_to_delete_nonexist_path(self):
173+
path="/root/test_dir"
174+
175+
assertself.operations.rmdirs(path,ignore_errors=False)isTrue
176+
177+
deftest_rmdirs__try_to_delete_file(self):
178+
path=self.operations.mkstemp()
179+
assertos.path.exists(path)
180+
181+
withpytest.raises(ExecUtilException)asx:
182+
self.operations.rmdirs(path,ignore_errors=False)
183+
184+
assertos.path.exists(path)
185+
asserttype(x.value)==ExecUtilException# noqa: E721
186+
assertx.value.message=="Utility exited with non-zero code (20). Error: `cannot remove '"+path+"': it is not a directory`"
187+
asserttype(x.value.error)==str# noqa: E721
188+
assertx.value.error.strip()=="cannot remove '"+path+"': it is not a directory"
189+
asserttype(x.value.exit_code)==int# noqa: E721
190+
assertx.value.exit_code==20
123191

124192
deftest_listdir(self):
125193
"""

‎tests/test_simple.py

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -428,16 +428,61 @@ def test_backup_wrong_xlog_method(self):
428428
node.backup(xlog_method='wrong')
429429

430430
deftest_pg_ctl_wait_option(self):
431-
withget_new_node()asnode:
432-
node.init().start(wait=False)
433-
whileTrue:
434-
try:
435-
node.stop(wait=False)
436-
break
437-
exceptExecUtilException:
438-
# it's ok to get this exception here since node
439-
# could be not started yet
440-
pass
431+
C_MAX_ATTEMPTS=50
432+
433+
node=get_new_node()
434+
assertnode.status()==testgres.NodeStatus.Uninitialized
435+
node.init()
436+
assertnode.status()==testgres.NodeStatus.Stopped
437+
node.start(wait=False)
438+
nAttempt=0
439+
whileTrue:
440+
ifnAttempt==C_MAX_ATTEMPTS:
441+
raiseException("Could not stop node.")
442+
443+
nAttempt+=1
444+
445+
ifnAttempt>1:
446+
logging.info("Wait 1 second.")
447+
time.sleep(1)
448+
logging.info("")
449+
450+
logging.info("Try to stop node. Attempt #{0}.".format(nAttempt))
451+
452+
try:
453+
node.stop(wait=False)
454+
break
455+
exceptExecUtilExceptionase:
456+
# it's ok to get this exception here since node
457+
# could be not started yet
458+
logging.info("Node is not stopped. Exception ({0}): {1}".format(type(e).__name__,e))
459+
continue
460+
461+
logging.info("OK. Stop command was executed. Let's wait while our node will stop really.")
462+
nAttempt=0
463+
whileTrue:
464+
ifnAttempt==C_MAX_ATTEMPTS:
465+
raiseException("Could not stop node.")
466+
467+
nAttempt+=1
468+
ifnAttempt>1:
469+
logging.info("Wait 1 second.")
470+
time.sleep(1)
471+
logging.info("")
472+
473+
logging.info("Attempt #{0}.".format(nAttempt))
474+
s1=node.status()
475+
476+
ifs1==testgres.NodeStatus.Running:
477+
continue
478+
479+
ifs1==testgres.NodeStatus.Stopped:
480+
break
481+
482+
raiseException("Unexpected node status: {0}.".format(s1))
483+
484+
logging.info("OK. Node is stopped.")
485+
node.cleanup()
441486

442487
deftest_replicate(self):
443488
withget_new_node()asnode:

‎tests/test_simple_remote.py

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -499,16 +499,61 @@ def test_backup_wrong_xlog_method(self):
499499
node.backup(xlog_method='wrong')
500500

501501
deftest_pg_ctl_wait_option(self):
502-
with__class__.helper__get_node()asnode:
503-
node.init().start(wait=False)
504-
whileTrue:
505-
try:
506-
node.stop(wait=False)
507-
break
508-
exceptExecUtilException:
509-
# it's ok to get this exception here since node
510-
# could be not started yet
511-
pass
502+
C_MAX_ATTEMPTS=50
503+
504+
node=__class__.helper__get_node()
505+
assertnode.status()==testgres.NodeStatus.Uninitialized
506+
node.init()
507+
assertnode.status()==testgres.NodeStatus.Stopped
508+
node.start(wait=False)
509+
nAttempt=0
510+
whileTrue:
511+
ifnAttempt==C_MAX_ATTEMPTS:
512+
raiseException("Could not stop node.")
513+
514+
nAttempt+=1
515+
516+
ifnAttempt>1:
517+
logging.info("Wait 1 second.")
518+
time.sleep(1)
519+
logging.info("")
520+
521+
logging.info("Try to stop node. Attempt #{0}.".format(nAttempt))
522+
523+
try:
524+
node.stop(wait=False)
525+
break
526+
exceptExecUtilExceptionase:
527+
# it's ok to get this exception here since node
528+
# could be not started yet
529+
logging.info("Node is not stopped. Exception ({0}): {1}".format(type(e).__name__,e))
530+
continue
531+
532+
logging.info("OK. Stop command was executed. Let's wait while our node will stop really.")
533+
nAttempt=0
534+
whileTrue:
535+
ifnAttempt==C_MAX_ATTEMPTS:
536+
raiseException("Could not stop node.")
537+
538+
nAttempt+=1
539+
ifnAttempt>1:
540+
logging.info("Wait 1 second.")
541+
time.sleep(1)
542+
logging.info("")
543+
544+
logging.info("Attempt #{0}.".format(nAttempt))
545+
s1=node.status()
546+
547+
ifs1==testgres.NodeStatus.Running:
548+
continue
549+
550+
ifs1==testgres.NodeStatus.Stopped:
551+
break
552+
553+
raiseException("Unexpected node status: {0}.".format(s1))
554+
555+
logging.info("OK. Node is stopped.")
556+
node.cleanup()
512557

513558
deftest_replicate(self):
514559
with__class__.helper__get_node()asnode:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp