Rev 4688: (mbp) warnings if extensions can't be loaded in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Mon Sep 14 04:01:27 BST 2009


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 4688 [merge]
revision-id: pqm at pqm.ubuntu.com-20090914030125-wichbbiuuk4260y4
parent: pqm at pqm.ubuntu.com-20090914014819-4yshlf6ooeeqznfs
parent: mbp at sourcefrog.net-20090914014828-ydr9rlkdfq2sv57z
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2009-09-14 04:01:25 +0100
message:
  (mbp) warnings if extensions can't be loaded
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
  bzrlib/annotate.py             annotate.py-20050922133147-7c60541d2614f022
  bzrlib/bencode.py              bencode.py-20070806220735-j75g4ebfnado2i60-2
  bzrlib/btree_index.py          index.py-20080624222253-p0x5f92uyh5hw734-7
  bzrlib/chk_map.py              chk_map.py-20081001014447-ue6kkuhofvdecvxa-1
  bzrlib/commands.py             bzr.py-20050309040720-d10f4714595cf8c3
  bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
  bzrlib/graph.py                graph_walker.py-20070525030359-y852guab65d4wtn0-1
  bzrlib/groupcompress.py        groupcompress.py-20080705181503-ccbxd6xuy1bdnrpu-8
  bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/rio.py                  rio.py-20051128032247-770b120b34dfff60
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
=== modified file 'NEWS'
--- a/NEWS	2009-09-11 14:23:16 +0000
+++ b/NEWS	2009-09-14 01:48:28 +0000
@@ -6,8 +6,8 @@
 .. contents:: List of Releases
    :depth: 1
 
-In Development
-##############
+2.1 series (not released yet)
+#############################
 
 Compatibility Breaks
 ********************
@@ -77,6 +77,14 @@
 Improvements
 ************
 
+* Bazaar gives a warning before exiting, and writes into ``.bzr.log``, if 
+  compiled extensions can't be loaded.  This typically indicates a
+  packaging or installation problem.  In this case Bazaar will keep
+  running using pure-Python versions, but this may be substantially
+  slower.  The warning can be disabled by setting
+  ``ignore_missing_extensions = True`` in ``bazaar.conf``.
+  (Martin Pool, #406113)
+
 Documentation
 *************
 

=== modified file 'bzrlib/__init__.py'
--- a/bzrlib/__init__.py	2009-08-30 21:34:42 +0000
+++ b/bzrlib/__init__.py	2009-09-14 01:48:28 +0000
@@ -55,6 +55,7 @@
 # API compatibility version: bzrlib is currently API compatible with 1.15.
 api_minimum_version = (1, 17, 0)
 
+
 def _format_version_tuple(version_info):
     """Turn a version number 2, 3 or 5-tuple into a short string.
 

=== modified file 'bzrlib/annotate.py'
--- a/bzrlib/annotate.py	2009-08-17 18:52:01 +0000
+++ b/bzrlib/annotate.py	2009-09-14 01:48:28 +0000
@@ -458,5 +458,6 @@
 
 try:
     from bzrlib._annotator_pyx import Annotator
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib._annotator_py import Annotator

=== modified file 'bzrlib/bencode.py'
--- a/bzrlib/bencode.py	2009-06-03 14:14:31 +0000
+++ b/bzrlib/bencode.py	2009-09-11 06:36:50 +0000
@@ -16,7 +16,10 @@
 
 """Wrapper around the bencode pyrex and python implementation"""
 
+from bzrlib import osutils
+
 try:
     from bzrlib._bencode_pyx import bdecode, bdecode_as_tuple, bencode, Bencached
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib.util._bencode_py import bdecode, bdecode_as_tuple, bencode, Bencached

=== modified file 'bzrlib/btree_index.py'
--- a/bzrlib/btree_index.py	2009-08-17 22:11:06 +0000
+++ b/bzrlib/btree_index.py	2009-09-14 01:48:28 +0000
@@ -1526,5 +1526,6 @@
 
 try:
     from bzrlib import _btree_serializer_pyx as _btree_serializer
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib import _btree_serializer_py as _btree_serializer

=== modified file 'bzrlib/chk_map.py'
--- a/bzrlib/chk_map.py	2009-08-04 14:10:09 +0000
+++ b/bzrlib/chk_map.py	2009-09-14 01:48:28 +0000
@@ -1640,7 +1640,8 @@
         _deserialise_leaf_node,
         _deserialise_internal_node,
         )
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib._chk_map_py import (
         _search_key_16,
         _search_key_255,

=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py	2009-09-09 17:51:19 +0000
+++ b/bzrlib/commands.py	2009-09-14 01:48:28 +0000
@@ -1107,6 +1107,7 @@
         argv = new_argv
     ret = run_bzr_catch_errors(argv)
     trace.mutter("return code %d", ret)
+    osutils.report_extension_load_failures()
     return ret
 
 

=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2009-08-28 05:00:33 +0000
+++ b/bzrlib/dirstate.py	2009-09-14 01:48:28 +0000
@@ -3969,7 +3969,8 @@
         ProcessEntryC as _process_entry,
         update_entry as update_entry,
         )
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib._dirstate_helpers_py import (
         _read_dirblocks,
         bisect_dirblock,

=== modified file 'bzrlib/graph.py'
--- a/bzrlib/graph.py	2009-08-17 18:36:14 +0000
+++ b/bzrlib/graph.py	2009-09-14 01:48:28 +0000
@@ -19,6 +19,7 @@
 from bzrlib import (
     debug,
     errors,
+    osutils,
     revision,
     trace,
     )
@@ -1681,5 +1682,6 @@
 _counters = [0,0,0,0,0,0,0]
 try:
     from bzrlib._known_graph_pyx import KnownGraph
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib._known_graph_py import KnownGraph

=== modified file 'bzrlib/groupcompress.py'
--- a/bzrlib/groupcompress.py	2009-09-09 13:05:33 +0000
+++ b/bzrlib/groupcompress.py	2009-09-14 01:48:28 +0000
@@ -2066,6 +2066,7 @@
         decode_base128_int,
         )
     GroupCompressor = PyrexGroupCompressor
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     GroupCompressor = PythonGroupCompressor
 

=== modified file 'bzrlib/knit.py'
--- a/bzrlib/knit.py	2009-09-09 13:05:33 +0000
+++ b/bzrlib/knit.py	2009-09-14 01:48:28 +0000
@@ -3700,5 +3700,6 @@
 
 try:
     from bzrlib._knit_load_data_pyx import _load_data_c as _load_data
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib._knit_load_data_py import _load_data_py as _load_data

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2009-07-23 16:01:17 +0000
+++ b/bzrlib/osutils.py	2009-09-11 06:39:56 +0000
@@ -21,6 +21,7 @@
                   S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
 import sys
 import time
+import warnings
 
 from bzrlib.lazy_import import lazy_import
 lazy_import(globals(), """
@@ -881,9 +882,56 @@
     return parents
 
 
+_extension_load_failures = []
+
+
+def failed_to_load_extension(exception):
+    """Handle failing to load a binary extension.
+
+    This should be called from the ImportError block guarding the attempt to
+    import the native extension.  If this function returns, the pure-Python
+    implementation should be loaded instead::
+
+    >>> try:
+    >>>     import bzrlib._fictional_extension_pyx
+    >>> except ImportError, e:
+    >>>     bzrlib.osutils.failed_to_load_extension(e)
+    >>>     import bzrlib._fictional_extension_py
+    """
+    # NB: This docstring is just an example, not a doctest, because doctest
+    # currently can't cope with the use of lazy imports in this namespace --
+    # mbp 20090729
+    
+    # This currently doesn't report the failure at the time it occurs, because
+    # they tend to happen very early in startup when we can't check config
+    # files etc, and also we want to report all failures but not spam the user
+    # with 10 warnings.
+    from bzrlib import trace
+    exception_str = str(exception)
+    if exception_str not in _extension_load_failures:
+        trace.mutter("failed to load compiled extension: %s" % exception_str)
+        _extension_load_failures.append(exception_str)
+
+
+def report_extension_load_failures():
+    if not _extension_load_failures:
+        return
+    from bzrlib.config import GlobalConfig
+    if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
+        return
+    # the warnings framework should by default show this only once
+    warnings.warn(
+        "bzr: warning: Failed to load compiled extensions:\n"
+        "    %s\n" 
+        "    Bazaar can run, but performance may be reduced.\n"
+        "    Check Bazaar is correctly installed or set ignore_missing_extensions"
+        % '\n    '.join(_extension_load_failures,))
+
+
 try:
     from bzrlib._chunks_to_lines_pyx import chunks_to_lines
-except ImportError:
+except ImportError, e:
+    failed_to_load_extension(e)
     from bzrlib._chunks_to_lines_py import chunks_to_lines
 
 
@@ -1466,7 +1514,8 @@
             try:
                 from bzrlib._readdir_pyx import UTF8DirReader
                 _selected_dir_reader = UTF8DirReader()
-            except ImportError:
+            except ImportError, e:
+                failed_to_load_extension(e)
                 pass
 
     if _selected_dir_reader is None:
@@ -1778,7 +1827,8 @@
         try:
             from bzrlib._readdir_pyx import UTF8DirReader
             file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
-        except ImportError:
+        except ImportError, e:
+            failed_to_load_extension(e)
             from bzrlib._readdir_py import (
                 _kind_from_mode as file_kind_from_stat_mode
                 )

=== modified file 'bzrlib/rio.py'
--- a/bzrlib/rio.py	2009-06-10 03:56:49 +0000
+++ b/bzrlib/rio.py	2009-09-11 06:36:50 +0000
@@ -32,6 +32,7 @@
 
 import re
 
+from bzrlib import osutils
 from bzrlib.iterablefile import IterableFile
 
 # XXX: some redundancy is allowing to write stanzas in isolation as well as
@@ -377,7 +378,8 @@
         _read_stanza_unicode,
         _valid_tag,
         )
-except ImportError:
+except ImportError, e:
+    osutils.failed_to_load_extension(e)
     from bzrlib._rio_py import (
        _read_stanza_utf8,
        _read_stanza_unicode,

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2009-07-23 16:01:17 +0000
+++ b/bzrlib/tests/test_osutils.py	2009-09-11 06:36:50 +0000
@@ -1798,3 +1798,33 @@
     def test_local_concurrency(self):
         concurrency = osutils.local_concurrency()
         self.assertIsInstance(concurrency, int)
+
+
+class TestFailedToLoadExtension(tests.TestCase):
+
+    def _try_loading(self):
+        try:
+            import bzrlib._fictional_extension_py
+        except ImportError, e:
+            osutils.failed_to_load_extension(e)
+            return True
+
+    def setUp(self):
+        super(TestFailedToLoadExtension, self).setUp()
+        self.saved_failures = osutils._extension_load_failures[:]
+        del osutils._extension_load_failures[:]
+        self.addCleanup(self.restore_failures)
+
+    def restore_failures(self):
+        osutils._extension_load_failures = self.saved_failures
+
+    def test_failure_to_load(self):
+        self._try_loading()
+        self.assertLength(1, osutils._extension_load_failures)
+        self.assertEquals(osutils._extension_load_failures[0],
+            "No module named _fictional_extension_py")
+
+    def test_report_extension_load_failures(self):
+        self.assertTrue(self._try_loading())
+        warnings, result = self.callCatchWarnings(osutils.report_extension_load_failures)
+        self.assertLength(1, warnings)




More information about the bazaar-commits mailing list