Skip to content

bpo-31920: Fix pygettext directory walk #4225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion Lib/test/test_tools/test_i18n.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Tests to cover the Tools/i18n package"""

import os
import re
import sys
import unittest

from test.support.script_helper import assert_python_ok
from test.test_tools import skip_if_missing, toolsdir
from test.support import temp_cwd
from test.support import temp_cwd, temp_dir


skip_if_missing()
Expand Down Expand Up @@ -72,3 +73,20 @@ def test_POT_Creation_Date(self):

# This will raise if the date format does not exactly match.
datetime.strptime(creationDate, '%Y-%m-%d %H:%M%z')

def test_files_list(self):
"""Make sure the directories are inspected for source files
bpo-31920
"""
source_dir = 'pypkg'
text = 'Text to translate'
with temp_cwd(None) as cwd:
with temp_dir(os.path.join(cwd, source_dir)) as sdir:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to use temp_dir(None) and test with a path that is not a child of the current directory. If pygettext.py ignores the argument and searches from the current directory, it will pass the current test, but not the test with independent test directory.

with open(os.path.join(sdir, 'pymod.py'), 'w') as sfile:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to put the test file deeper in the directory tree, e.g. in os.path.join(sdir, 'pypkg', 'pymod.py'). This would test that directories are searched recursively.

sfile.write('_("{}")'.format(text))
assert_python_ok(self.script, source_dir)
with open('messages.pot') as fp:
data = fp.read()
msgids = re.findall(r'msgid "(.*?)"', data)

self.assertIn(text, msgids)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't be simpler to test the containment directly in the file content?

self.assertIn('msgid "%s"' % text, data)

30 changes: 11 additions & 19 deletions Tools/i18n/pygettext.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,24 +259,6 @@ def containsAny(str, set):
return 1 in [c in str for c in set]


def _visit_pyfiles(list, dirname, names):
"""Helper for getFilesForName()."""
# get extension for python source files
if '_py_ext' not in globals():
global _py_ext
_py_ext = importlib.machinery.SOURCE_SUFFIXES[0]

# don't recurse into CVS directories
if 'CVS' in names:
names.remove('CVS')

# add all *.py files to list
list.extend(
[os.path.join(dirname, file) for file in names
if os.path.splitext(file)[1] == _py_ext]
)


def getFilesForName(name):
"""Get a list of module files for a filename, a module or package name,
or a directory.
Expand All @@ -302,7 +284,17 @@ def getFilesForName(name):
if os.path.isdir(name):
# find all python files in directory
list = []
os.walk(name, _visit_pyfiles, list)
# get extension for python source files
_py_ext = importlib.machinery.SOURCE_SUFFIXES[0]
for root, dirs, files in os.walk(name):
# don't recurse into CVS directories
if 'CVS' in dirs:
dirs.remove('CVS')
# add all *.py files to list
list.extend(
[os.path.join(root, file) for file in files
if os.path.splitext(file)[1] == _py_ext]
)
return list
elif os.path.exists(name):
# a single file
Expand Down