Skip to content

Commit 8e479de

Browse files
committed
refactor!: replace os.listdir() with os.scandir()
In many places we did a listdir() then a stat to see if it's a file or directory. This change removes the need for the stat call. Also for larger directories, scandir() is an iterator, so less memory use. There is one remnant of listdir used in an error handler. That requires a stat on each element in the directory, so there is no benefit to using scandir() other than a slight memory saving on a rarely used piece of code. BREAKING CHANGE: Python 2 requires installation of scandir pip package after this commit.
1 parent b334b94 commit 8e479de

File tree

6 files changed

+22
-19
lines changed

6 files changed

+22
-19
lines changed

roundup/admin.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,16 +1226,17 @@ class colon_separated(csv.excel):
12261226
delimiter = ':'
12271227

12281228
# import all the files
1229-
for file in os.listdir(import_dir):
1230-
classname, ext = os.path.splitext(file)
1229+
for dir_entry in os.scandir(import_dir):
1230+
filename = dir_entry.name
1231+
classname, ext = os.path.splitext(filename)
12311232
# we only care about CSV files
12321233
if ext != '.csv' or classname.endswith('-journals'):
12331234
continue
12341235

12351236
cl = self.get_class(classname)
12361237

12371238
# ensure that the properties and the CSV file headings match
1238-
with open(os.path.join(import_dir, file), 'r') as f:
1239+
with open(os.path.join(import_dir, filename), 'r') as f:
12391240
reader = csv.reader(f, colon_separated, lineterminator='\n')
12401241
file_props = None
12411242
maxid = 1

roundup/backends/blobfiles.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@ def files_in_dir(dir):
2727
if not os.path.exists(dir):
2828
return 0
2929
num_files = 0
30-
for dir_entry in os.listdir(dir):
31-
full_filename = os.path.join(dir, dir_entry)
32-
if os.path.isfile(full_filename):
30+
for dir_entry in os.scandir(dir):
31+
if dir_entry.is_file():
3332
num_files = num_files + 1
34-
elif os.path.isdir(full_filename):
35-
num_files = num_files + files_in_dir(full_filename)
33+
elif dir_entry.is_dir():
34+
num_files = num_files + files_in_dir(dir_entry.path)
3635
return num_files
3736

3837

roundup/cgi/templating.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,10 @@ def check(self, name):
334334

335335
def precompile(self):
336336
""" Precompile templates in load directory by loading them """
337-
for filename in os.listdir(self.template_dir):
337+
for dir_entry in os.scandir(self.template_dir):
338+
filename = dir_entry.name
338339
# skip subdirs
339-
if os.path.isdir(filename):
340+
if dir_entry.is_dir():
340341
continue
341342

342343
# skip files without ".html" or ".xml" extension - .css, .js etc.

roundup/init.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def copytree(src, dst, symlinks=0):
4444
"""
4545

4646
# Prevent 'hidden' files (those starting with '.') from being considered.
47-
names = [f for f in os.listdir(src) if not f.startswith('.')]
47+
names = [f.name for f in os.scandir(src) if not f.name.startswith('.')]
4848
try:
4949
os.mkdir(dst)
5050
except OSError as error:
@@ -111,17 +111,16 @@ def install(instance_home, template, settings={}):
111111
config.save(config_ini_file)
112112

113113

114-
def listTemplates(dir):
114+
def listTemplates(directory):
115115
''' List all the Roundup template directories in a given directory.
116116
117117
Find all the dirs that contain a TEMPLATE-INFO.txt and parse it.
118118
119119
Return a list of dicts of info about the templates.
120120
'''
121121
ret = {}
122-
for idir in os.listdir(dir):
123-
idir = os.path.join(dir, idir)
124-
ti = loadTemplateInfo(idir)
122+
for dir_entry in os.scandir(directory):
123+
ti = loadTemplateInfo(dir_entry.path)
125124
if ti:
126125
ret[ti['name']] = ti
127126
return ret

roundup/instance.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ def get_extensions(self, dirname):
188188
dirpath = os.path.join(self.tracker_home, dirname)
189189
if os.path.isdir(dirpath):
190190
sys.path.insert(1, dirpath)
191-
for name in os.listdir(dirpath):
191+
for dir_entry in os.scandir(dirpath):
192+
name = dir_entry.name
192193
if not name.endswith('.py'):
193194
continue
194195
env = {}

roundup/scripts/roundup_gettext.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class Options:
6464
TEMPLATE_FILE = "messages.pot"
6565

6666

67+
# FIXME: html directory can be specified in config.ini. Should be
68+
# a parameter, or config.ini should be loaded.
6769
def run():
6870
# return unless command line arguments contain single directory path
6971
if (len(sys.argv) != 2) or (sys.argv[1] in ("-h", "--help")):
@@ -76,9 +78,9 @@ def run():
7678
if os.path.isdir(htmldir):
7779
# glob is not used because i want to match file names
7880
# without case sensitivity, and that is easier done this way.
79-
htmlfiles = [filename for filename in os.listdir(htmldir)
80-
if os.path.isfile(os.path.join(htmldir, filename))
81-
and filename.lower().endswith(".html")]
81+
htmlfiles = [e.name for e in os.scandir(htmldir)
82+
if e.is_file()
83+
and e.name.lower().endswith(".html")]
8284
else:
8385
htmlfiles = []
8486
# return if no html files found

0 commit comments

Comments
 (0)