diff options
-rw-r--r-- | HACKING.rst | 12 | ||||
-rwxr-xr-x | bin/oslo-rootwrap | 4 | ||||
-rw-r--r-- | openstack/common/exception.py | 11 | ||||
-rw-r--r-- | openstack/common/rpc/common.py | 2 | ||||
-rw-r--r-- | openstack/common/rpc/impl_zmq.py | 33 | ||||
-rw-r--r-- | openstack/common/version.py | 13 | ||||
-rw-r--r-- | tests/unit/test_exception.py | 3 | ||||
-rw-r--r-- | tests/unit/test_setup.py | 114 | ||||
-rw-r--r-- | tests/utils.py | 8 |
9 files changed, 167 insertions, 33 deletions
diff --git a/HACKING.rst b/HACKING.rst index 7dda11a..3f6a3ed 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -27,6 +27,18 @@ General mylist = Foo().list() # OKAY, does not shadow built-in +- Use the "not in" operator for collection membership evaluation. Example:: + + if not X in Y: # BAD, hard to understand + pass + + if X not in Y: # OKAY, intuitive + pass + + if not (X in Y or X is Z): # OKAY, still better than all those 'not's + pass + + TODO vs FIXME ------------- diff --git a/bin/oslo-rootwrap b/bin/oslo-rootwrap index 12b2379..4f5f33b 100755 --- a/bin/oslo-rootwrap +++ b/bin/oslo-rootwrap @@ -105,8 +105,8 @@ if __name__ == '__main__': exec_dirs=config.exec_dirs) if config.use_syslog: logging.info("(%s > %s) Executing %s (filter match = %s)" % ( - os.getlogin(), pwd.getpwuid(os.getuid())[0], - command, filtermatch.name)) + os.getlogin(), pwd.getpwuid(os.getuid())[0], + command, filtermatch.name)) obj = subprocess.Popen(command, stdin=sys.stdin, diff --git a/openstack/common/exception.py b/openstack/common/exception.py index fa06d6a..4a7c72b 100644 --- a/openstack/common/exception.py +++ b/openstack/common/exception.py @@ -23,6 +23,8 @@ import logging from openstack.common.gettextutils import _ +_FATAL_EXCEPTION_FORMAT_ERRORS = False + class Error(Exception): def __init__(self, message=None): @@ -121,9 +123,12 @@ class OpenstackException(Exception): try: self._error_string = self.message % kwargs - except Exception: - # at least get the core message out if something happened - self._error_string = self.message + except Exception as e: + if _FATAL_EXCEPTION_FORMAT_ERRORS: + raise e + else: + # at least get the core message out if something happened + self._error_string = self.message def __str__(self): return self._error_string diff --git a/openstack/common/rpc/common.py b/openstack/common/rpc/common.py index 8af2f03..357ee9d 100644 --- a/openstack/common/rpc/common.py +++ b/openstack/common/rpc/common.py @@ -289,7 +289,7 @@ def deserialize_remote_exception(conf, data): # NOTE(ameade): We DO NOT want to allow just any module to be imported, in # order to prevent arbitrary code execution. - if not module in conf.allowed_rpc_exception_modules: + if module not in conf.allowed_rpc_exception_modules: return RemoteError(name, failure.get('message'), trace) try: diff --git a/openstack/common/rpc/impl_zmq.py b/openstack/common/rpc/impl_zmq.py index 86d2bc5..0e998e9 100644 --- a/openstack/common/rpc/impl_zmq.py +++ b/openstack/common/rpc/impl_zmq.py @@ -17,7 +17,6 @@ import os import pprint import socket -import string import sys import types import uuid @@ -321,21 +320,22 @@ class ConsumerBase(object): return [result] def process(self, style, target, proxy, ctx, data): + data.setdefault('version', None) + data.setdefault('args', {}) + # Method starting with - are # processed internally. (non-valid method name) - method = data['method'] + method = data.get('method') + if not method: + LOG.error(_("RPC message did not include method.")) + return # Internal method # uses internal context for safety. - if data['method'][0] == '-': - # For reply / process_reply - method = method[1:] - if method == 'reply': - self.private_ctx.reply(ctx, proxy, **data['args']) + if method == '-reply': + self.private_ctx.reply(ctx, proxy, **data['args']) return - data.setdefault('version', None) - data.setdefault('args', {}) proxy.dispatch(ctx, data['version'], data['method'], **data['args']) @@ -780,18 +780,5 @@ def _get_ctxt(): def _get_matchmaker(): global matchmaker if not matchmaker: - # rpc_zmq_matchmaker should be set to a 'module.Class' - mm_path = CONF.rpc_zmq_matchmaker.split('.') - mm_module = '.'.join(mm_path[:-1]) - mm_class = mm_path[-1] - - # Only initialize a class. - if mm_path[-1][0] not in string.ascii_uppercase: - LOG.error(_("Matchmaker could not be loaded.\n" - "rpc_zmq_matchmaker is not a class.")) - raise RPCException(_("Error loading Matchmaker.")) - - mm_impl = importutils.import_module(mm_module) - mm_constructor = getattr(mm_impl, mm_class) - matchmaker = mm_constructor() + matchmaker = importutils.import_object(CONF.rpc_zmq_matchmaker) return matchmaker diff --git a/openstack/common/version.py b/openstack/common/version.py index 3653ad0..c27095a 100644 --- a/openstack/common/version.py +++ b/openstack/common/version.py @@ -36,9 +36,16 @@ class VersionInfo(object): def _get_version_from_pkg_resources(self): """Get the version of the package from the pkg_resources record associated with the package.""" - requirement = pkg_resources.Requirement.parse(self.package) - provider = pkg_resources.get_provider(requirement) - return provider.version + try: + requirement = pkg_resources.Requirement.parse(self.package) + provider = pkg_resources.get_provider(requirement) + return provider.version + except pkg_resources.DistributionNotFound: + # The most likely cause for this is running tests in a tree with + # produced from a tarball where the package itself has not been + # installed into anything. Check for a PKG-INFO file. + from openstack.common import setup + return setup.get_version_from_pkg_info(self.package) def release_string(self): """Return the full version of the package including suffixes indicating diff --git a/tests/unit/test_exception.py b/tests/unit/test_exception.py index c03a41d..6fe93ac 100644 --- a/tests/unit/test_exception.py +++ b/tests/unit/test_exception.py @@ -88,7 +88,8 @@ class OpenstackExceptionTest(utils.BaseTestCase): err = self.TestException(test=test_message) self.assertEqual(err._error_string, test_message) - def test_error_forating_error_string(self): + def test_error_formating_error_string(self): + self.stubs.Set(exception, '_FATAL_EXCEPTION_FORMAT_ERRORS', False) err = self.TestException(lol='U mad brah') self.assertEqual(err._error_string, self.TestException.message) diff --git a/tests/unit/test_setup.py b/tests/unit/test_setup.py index dfd8841..8f6324d 100644 --- a/tests/unit/test_setup.py +++ b/tests/unit/test_setup.py @@ -17,6 +17,7 @@ import os import sys +import StringIO from tempfile import mkstemp import fixtures @@ -25,6 +26,22 @@ from openstack.common.setup import * from tests import utils +class DiveDir(fixtures.Fixture): + """Dive into given directory and return back on cleanup. + + :ivar path: The target directory. + """ + + def __init__(self, path): + self.path = path + + def setUp(self): + super(DiveDir, self).setUp() + self.old_path = os.getcwd() + os.chdir(self.path) + self.addCleanup(os.chdir, self.old_path) + + class EmailTestCase(utils.BaseTestCase): def test_str_dict_replace(self): @@ -60,6 +77,77 @@ class MailmapTestCase(utils.BaseTestCase): parse_mailmap(self.mailmap)) +class GitLogsTest(utils.BaseTestCase): + + def setUp(self): + super(GitLogsTest, self).setUp() + temp_path = self.useFixture(fixtures.TempDir()).path + self.useFixture(DiveDir(temp_path)) + self.useFixture(fixtures.MonkeyPatch("os.path.isdir", + lambda path: path == ".git")) + + def test_write_git_changelog(self): + self.useFixture(fixtures.FakePopen(lambda _: { + "stdout": StringIO.StringIO("Author: Foo Bar <email@bar.com>\n") + })) + with open(".mailmap", "w") as mm_fh: + mm_fh.write("Foo Bar <email@foo.com> <email@bar.com>\n") + + write_git_changelog() + + with open("ChangeLog", "r") as ch_fh: + self.assertTrue("email@foo.com" in ch_fh.read()) + + def test_generate_authors(self): + author_old = "Foo Foo <email@foo.com>" + author_new = "Bar Bar <email@bar.com>" + + self.useFixture(fixtures.FakePopen(lambda proc_args: { + "stdout": StringIO.StringIO( + author_new + if proc_args["args"][2].startswith("git log") + else "") + })) + + with open("AUTHORS.in", "w") as auth_fh: + auth_fh.write(author_old) + + generate_authors() + + with open("AUTHORS", "r") as auth_fh: + authors = auth_fh.read() + self.assertTrue(author_old in authors) + self.assertTrue(author_new in authors) + + +class GetCmdClassTest(utils.BaseTestCase): + + def test_get_cmdclass(self): + cmdclass = get_cmdclass() + + self.assertTrue("sdist" in cmdclass) + build_sphinx = cmdclass.get("build_sphinx") + if build_sphinx: + self.useFixture(fixtures.MonkeyPatch( + "sphinx.setup_command.BuildDoc.run", lambda self: None)) + from distutils.dist import Distribution + distr = Distribution() + distr.packages = ("fake_package",) + distr.command_options["build_sphinx"] = {"source_dir": ["a", "."]} + pkg_fixture = fixtures.PythonPackage( + "fake_package", [("fake_module.py", "")]) + self.useFixture(pkg_fixture) + self.useFixture(DiveDir(pkg_fixture.base)) + + build_doc = build_sphinx(distr) + build_doc.run() + + self.assertTrue( + os.path.exists("api/autoindex.rst")) + self.assertTrue( + os.path.exists("api/fake_package.fake_module.rst")) + + class ParseRequirementsTest(utils.BaseTestCase): def setUp(self): @@ -93,3 +181,29 @@ class ParseRequirementsTest(utils.BaseTestCase): fh.write("argparse") if sys.version_info >= (2, 7): self.assertEqual([], parse_requirements([self.tmp_file])) + + def test_get_requirement_from_file_empty(self): + actual = get_reqs_from_files([]) + self.assertEqual([], actual) + + +class ParseDependencyLinksTest(utils.BaseTestCase): + + def setUp(self): + super(ParseDependencyLinksTest, self).setUp() + self.useFixture(fixtures.NestedTempfile()) + (fd, self.tmp_file) = mkstemp(prefix="openstack", suffix=".setup") + + def test_parse_dependency_normal(self): + with open(self.tmp_file, "w") as fh: + fh.write("http://test.com\n") + self.assertEqual( + ["http://test.com"], + parse_dependency_links([self.tmp_file])) + + def test_parse_dependency_with_git_egg_url(self): + with open(self.tmp_file, "w") as fh: + fh.write("-e git://foo.com/zipball#egg=bar") + self.assertEqual( + ["git://foo.com/zipball#egg=bar"], + parse_dependency_links([self.tmp_file])) diff --git a/tests/utils.py b/tests/utils.py index f9854ca..2d681ae 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -24,6 +24,7 @@ import testtools from openstack.common import cfg from openstack.common.fixture import moxstubout +from openstack.common import exception CONF = cfg.CONF @@ -36,6 +37,13 @@ class BaseTestCase(testtools.TestCase): self.addCleanup(CONF.reset) self.useFixture(fixtures.FakeLogger('openstack.common')) self.useFixture(fixtures.Timeout(30, True)) + self.stubs.Set(exception, '_FATAL_EXCEPTION_FORMAT_ERRORS', True) + + def tearDown(self): + super(BaseTestCase, self).tearDown() + CONF.reset() + self.stubs.UnsetAll() + self.stubs.SmartUnsetAll() def config(self, **kw): """ |