Files
deb-python-extras/extras/tests/test_extras.py
2016-05-18 20:58:37 +12:00

208 lines
6.9 KiB
Python

# Copyright (c) 2010-2012 extras developers. See LICENSE for details.
import sys
import types
from testtools import TestCase
from testtools.matchers import (
Equals,
Is,
Not,
)
from extras import (
safe_hasattr,
try_import,
try_imports,
)
def check_error_callback(test, function, arg, expected_error_count,
expect_result):
"""General test template for error_callback argument.
:param test: Test case instance.
:param function: Either try_import or try_imports.
:param arg: Name or names to import.
:param expected_error_count: Expected number of calls to the callback.
:param expect_result: Boolean for whether a module should
ultimately be returned or not.
"""
cb_calls = []
def cb(e):
test.assertIsInstance(e, ImportError)
cb_calls.append(e)
try:
result = function(arg, error_callback=cb)
except ImportError:
test.assertFalse(expect_result)
else:
if expect_result:
test.assertThat(result, Not(Is(None)))
else:
test.assertThat(result, Is(None))
test.assertEquals(len(cb_calls), expected_error_count)
class TestSafeHasattr(TestCase):
def test_attribute_not_there(self):
class Foo(object):
pass
self.assertEqual(False, safe_hasattr(Foo(), 'anything'))
def test_attribute_there(self):
class Foo(object):
pass
foo = Foo()
foo.attribute = None
self.assertEqual(True, safe_hasattr(foo, 'attribute'))
def test_property_there(self):
class Foo(object):
@property
def attribute(self):
return None
foo = Foo()
self.assertEqual(True, safe_hasattr(foo, 'attribute'))
def test_property_raises(self):
class Foo(object):
@property
def attribute(self):
1/0
foo = Foo()
self.assertRaises(ZeroDivisionError, safe_hasattr, foo, 'attribute')
class TestTryImport(TestCase):
def test_doesnt_exist(self):
# try_import('thing', foo) returns foo if 'thing' doesn't exist.
marker = object()
result = try_import('doesntexist', marker)
self.assertThat(result, Is(marker))
def test_None_is_default_alternative(self):
# try_import('thing') returns None if 'thing' doesn't exist.
result = try_import('doesntexist')
self.assertThat(result, Is(None))
def test_existing_module(self):
# try_import('thing', foo) imports 'thing' and returns it if it's a
# module that exists.
result = try_import('os', object())
import os
self.assertThat(result, Is(os))
def test_existing_submodule(self):
# try_import('thing.another', foo) imports 'thing' and returns it if
# it's a module that exists.
result = try_import('os.path', object())
import os
self.assertThat(result, Is(os.path))
def test_nonexistent_submodule(self):
# try_import('thing.another', foo) imports 'thing' and returns foo if
# 'another' doesn't exist.
marker = object()
result = try_import('os.doesntexist', marker)
self.assertThat(result, Is(marker))
def test_object_from_module(self):
# try_import('thing.object') imports 'thing' and returns
# 'thing.object' if 'thing' is a module and 'object' is not.
result = try_import('os.path.join')
import os
self.assertThat(result, Is(os.path.join))
def test_error_callback(self):
# the error callback is called on failures.
check_error_callback(self, try_import, 'doesntexist', 1, False)
def test_error_callback_missing_module_member(self):
# the error callback is called on failures to find an object
# inside an existing module.
check_error_callback(self, try_import, 'os.nonexistent', 1, False)
def test_error_callback_not_on_success(self):
# the error callback is not called on success.
check_error_callback(self, try_import, 'os.path', 0, True)
def test_handle_partly_imported_name(self):
# try_import('thing.other') when thing.other is mid-import
# used to fail because thing.other is not assigned until thing.other
# finishes its import - but thing.other is accessible via sys.modules.
outer = types.ModuleType("extras.outer")
inner = types.ModuleType("extras.outer.inner")
inner.attribute = object()
self.addCleanup(sys.modules.pop, "extras.outer", None)
self.addCleanup(sys.modules.pop, "extras.outer.inner", None)
sys.modules["extras.outer"] = outer
sys.modules["extras.outer.inner"] = inner
result = try_import("extras.outer.inner.attribute")
self.expectThat(result, Is(inner.attribute))
result = try_import("extras.outer.inner")
self.expectThat(result, Is(inner))
class TestTryImports(TestCase):
def test_doesnt_exist(self):
# try_imports('thing', foo) returns foo if 'thing' doesn't exist.
marker = object()
result = try_imports(['doesntexist'], marker)
self.assertThat(result, Is(marker))
def test_fallback(self):
result = try_imports(['doesntexist', 'os'])
import os
self.assertThat(result, Is(os))
def test_None_is_default_alternative(self):
# try_imports('thing') returns None if 'thing' doesn't exist.
e = self.assertRaises(
ImportError, try_imports, ['doesntexist', 'noreally'])
self.assertThat(
str(e),
Equals("Could not import any of: doesntexist, noreally"))
def test_existing_module(self):
# try_imports('thing', foo) imports 'thing' and returns it if it's a
# module that exists.
result = try_imports(['os'], object())
import os
self.assertThat(result, Is(os))
def test_existing_submodule(self):
# try_imports('thing.another', foo) imports 'thing' and returns it if
# it's a module that exists.
result = try_imports(['os.path'], object())
import os
self.assertThat(result, Is(os.path))
def test_nonexistent_submodule(self):
# try_imports('thing.another', foo) imports 'thing' and returns foo if
# 'another' doesn't exist.
marker = object()
result = try_imports(['os.doesntexist'], marker)
self.assertThat(result, Is(marker))
def test_fallback_submodule(self):
result = try_imports(['os.doesntexist', 'os.path'])
import os
self.assertThat(result, Is(os.path))
def test_error_callback(self):
# One error for every class that doesn't exist.
check_error_callback(self, try_imports,
['os.doesntexist', 'os.notthiseither'],
2, False)
check_error_callback(self, try_imports,
['os.doesntexist', 'os.notthiseither', 'os'],
2, True)
check_error_callback(self, try_imports,
['os.path'],
0, True)