Skip to content

Commit 6ef90c0

Browse files
jacobaustin123copybara-github
authored andcommitted
Updated to fix unittest compatibility and Python 3.4 backwards compatibility.
PiperOrigin-RevId: 339798577 Change-Id: I94655e65e19dc56d6ee608e84ec02056558154d3
1 parent c1a0450 commit 6ef90c0

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

fire/__main__.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
# Lint as: python2, python3
1516
# pylint: disable=invalid-name
16-
"""Enables use of Python Fire as a "main" function (i.e. `python -m fire`).
17+
"""Enables use of Python Fire as a "main" function (i.e. "python -m fire").
1718
1819
This allows using Fire with third-party libraries without modifying their code.
1920
"""
@@ -39,21 +40,34 @@
3940

4041

4142
def import_from_file_path(path):
42-
"""Performs a module import given the filename."""
43+
"""Performs a module import given the filename.
44+
45+
Args:
46+
path (str): the path to the file to be imported.
47+
48+
Raises:
49+
IOError: if the given file does not exist or importlib fails to load it.
50+
51+
Returns:
52+
Tuple[ModuleType, str]: returns the imported module and the module name,
53+
usually extracted from the path itself.
54+
"""
55+
56+
if not os.path.exists(path):
57+
raise IOError('Given file path does not exist.')
58+
4359
module_name = os.path.basename(path)
4460

4561
if sys.version_info.major == 3 and sys.version_info.minor < 5:
4662
loader = importlib.machinery.SourceFileLoader(
4763
fullname=module_name,
4864
path=path,
4965
)
50-
spec = importlib.util.spec_from_loader(loader.name, loader, origin=path)
51-
module = importlib.util.module_from_spec(spec)
52-
sys.modules[loader.name] = module
53-
loader.exec_module(module)
66+
67+
module = loader.load_module(module_name) # pylint: disable=deprecated-method
5468

5569
elif sys.version_info.major == 3:
56-
from importlib import util # pylint: disable=g-import-not-at-top
70+
from importlib import util # pylint: disable=g-import-not-at-top,import-outside-toplevel
5771
spec = util.spec_from_file_location(module_name, path)
5872

5973
if spec is None:
@@ -63,19 +77,35 @@ def import_from_file_path(path):
6377
spec.loader.exec_module(module) # pytype: disable=attribute-error
6478

6579
else:
66-
import imp # pylint: disable=g-import-not-at-top
80+
import imp # pylint: disable=g-import-not-at-top,import-outside-toplevel
6781
module = imp.load_source(module_name, path)
6882

6983
return module, module_name
7084

7185

7286
def import_from_module_name(module_name):
87+
"""Imports a module and returns it and its name."""
7388
module = importlib.import_module(module_name)
7489
return module, module_name
7590

7691

7792
def import_module(module_or_filename):
78-
"""Imports a given module or filename."""
93+
"""Imports a given module or filename.
94+
95+
If the module_or_filename exists in the file system and ends with .py, we
96+
attempt to import it. If that import fails, try to import it as a module.
97+
98+
Args:
99+
module_or_filename (str): string name of path or module.
100+
101+
Raises:
102+
ValueError: if the given file is invalid.
103+
IOError: if the file or module can not be found or imported.
104+
105+
Returns:
106+
Tuple[ModuleType, str]: returns the imported module and the module name,
107+
usually extracted from the path itself.
108+
"""
79109

80110
if os.path.exists(module_or_filename):
81111
# importlib.util.spec_from_file_location requires .py
@@ -98,7 +128,7 @@ def main(args):
98128

99129
if len(args) < 2:
100130
print(cli_string)
101-
exit(1)
131+
sys.exit(1)
102132

103133
module_or_filename = args[1]
104134
module, module_name = import_module(module_or_filename)

fire/testutils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
# Lint as: python2, python3
1516
"""Utilities for Python Fire's tests."""
1617

1718
from __future__ import absolute_import
@@ -72,6 +73,12 @@ def assertOutputMatches(self, stdout='.*', stderr='.*', capture=True):
7273
raise AssertionError('%s: Expected %r to match %r' %
7374
(name, value, regexp))
7475

76+
def assertRaisesRegex(self, *args, **kwargs):
77+
if sys.version_info.major == 2:
78+
return super(BaseTestCase, self).assertRaisesRegexp(*args, **kwargs) # pylint: disable=deprecated-method
79+
else:
80+
return super(BaseTestCase, self).assertRaisesRegex(*args, **kwargs)
81+
7582
@contextlib.contextmanager
7683
def assertRaisesFireExit(self, code, regexp='.*'):
7784
"""Asserts that a FireExit error is raised in the context.
@@ -100,6 +107,7 @@ def assertRaisesFireExit(self, code, regexp='.*'):
100107

101108
@contextlib.contextmanager
102109
def ChangeDirectory(directory):
110+
"""Context manager to mock a directory change and revert on exit."""
103111
cwdir = os.getcwd()
104112
os.chdir(directory)
105113

0 commit comments

Comments
 (0)