Skip to content

Commit 80caec4

Browse files
committed
feat: added a safe_listdir function
1 parent f6d1af3 commit 80caec4

File tree

1 file changed

+32
-1
lines changed
  • src/DIRAC/Core/Utilities

1 file changed

+32
-1
lines changed

src/DIRAC/Core/Utilities/Os.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
by default on Error they return None
44
"""
55
import os
6+
import threading
67

78
import DIRAC
8-
from DIRAC.Core.Utilities.Subprocess import shellCall, systemCall
99
from DIRAC.Core.Utilities import List
10+
from DIRAC.Core.Utilities.Subprocess import shellCall, systemCall
1011

1112
DEBUG = 0
1213

@@ -128,3 +129,33 @@ def sourceEnv(timeout, cmdTuple, inputEnv=None):
128129
result["stderr"] = stderr
129130

130131
return result
132+
133+
134+
def safe_listdir(directory, timeout=60):
135+
"""This is a "safe" list directory,
136+
for lazily-loaded File Systems like CVMFS.
137+
There's by default a 60 seconds timeout.
138+
139+
.. warning::
140+
There is no distinction between an empty directory, and a non existent one.
141+
It will return `[]` in both cases.
142+
143+
:param str directory: directory to list
144+
:param int timeout: optional timeout, in seconds. Defaults to 60.
145+
"""
146+
147+
def listdir(directory):
148+
try:
149+
return os.listdir(directory)
150+
except FileNotFoundError:
151+
print(f"{directory} not found")
152+
return []
153+
154+
contents = []
155+
t = threading.Thread(target=lambda: contents.extend(listdir(directory)))
156+
t.daemon = True # don't delay program's exit
157+
t.start()
158+
t.join(timeout)
159+
if t.is_alive():
160+
return None # timeout
161+
return contents

0 commit comments

Comments
 (0)