Merge lp:~mbp/bzr/406113-extension-warnings into lp:bzr

Proposed by Martin Pool
Status: Merged
Approved by: John A Meinel
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~mbp/bzr/406113-extension-warnings
Merge into: lp:bzr
Diff against target: None lines
To merge this branch: bzr merge lp:~mbp/bzr/406113-extension-warnings
Reviewer Review Type Date Requested Status
John A Meinel Approve
Review via email: mp+11584@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Martin Pool (mbp) wrote :

Here's an update for the bug 406113 taking into account John's comments in the previous review.

We now give just one warning, at the end of running bzr, describing all modules that failed to load.

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Pool wrote:
> Martin Pool has proposed merging lp:~mbp/bzr/406113-extension-warnings into lp:bzr.
>
> Requested reviews:
> bzr-core (bzr-core)
>
> Here's an update for the bug 406113 taking into account John's comments in the previous review.
>
> We now give just one warning, at the end of running bzr, describing all modules that failed to load.
>

I like it, though I'm a little concerned about:
+ 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,))

^- "Bazaar can run" is being issued after Bazaar finishes running. I
can't think off-hand of a better way to write it, though. So

  review: approve
  merge: approve

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkqqPGUACgkQJdeBCYSNAANLRwCgs6UGupgQYRLX1QA/lE88U9Vk
hugAn2dcrgFkwauP1wHQIbTme3f2RH9m
=7yI0
-----END PGP SIGNATURE-----

review: Approve
Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Pool wrote:
> Martin Pool has proposed merging lp:~mbp/bzr/406113-extension-warnings into lp:bzr.
>
> Requested reviews:
> bzr-core (bzr-core)
>
> Here's an update for the bug 406113 taking into account John's comments in the previous review.
>
> We now give just one warning, at the end of running bzr, describing all modules that failed to load.
>

So with this new version, I just started getting the failure on
Kerguelen. So I went to investigate, but I can't get any real info. This
is what is in .bzr.log:

Tue 2009-09-22 14:18:26 +1000
0.266 bzr arguments: [u'--version']
0.406 encoding stdout as sys.stdout encoding 'cp437'
0.641 failed to load compiled extension: DLL load failed: Access is denied.
0.844 opening working tree 'C:/home/shared/bzr/bzr.dev'
6.344 return code 0
[58364] 2009-09-22 14:18:33.082 WARNING: bzr: warning: some compiled
extensions could not be loaded; see
<https://answers.launchpad.net/bzr/+faq/703>

So it says "I can't load" but it doesn't say *what* fails to load, and
with the shorter error, you don't show the summary of what failed to
load either.

- -Derror doesn't seem to help.

So I would recommend and least dropping the list of failures into the
log file.

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkq4UOoACgkQJdeBCYSNAAPh2QCeOoJIYy3Xie8UHG5u0fJtYrvK
rFQAoJhwF6fepodbW2uI3PUO7YVvDq3S
=l3m6
-----END PGP SIGNATURE-----

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

John A Meinel wrote:
> Martin Pool wrote:
>> Martin Pool has proposed merging lp:~mbp/bzr/406113-extension-warnings into lp:bzr.
>
>> Requested reviews:
>> bzr-core (bzr-core)
>
>> Here's an update for the bug 406113 taking into account John's comments in the previous review.
>
>> We now give just one warning, at the end of running bzr, describing all modules that failed to load.
>
>
> So with this new version, I just started getting the failure on
> Kerguelen. So I went to investigate, but I can't get any real info. This
> is what is in .bzr.log:
>
> Tue 2009-09-22 14:18:26 +1000
> 0.266 bzr arguments: [u'--version']
> 0.406 encoding stdout as sys.stdout encoding 'cp437'
> 0.641 failed to load compiled extension: DLL load failed: Access is denied.
> 0.844 opening working tree 'C:/home/shared/bzr/bzr.dev'
> 6.344 return code 0
> [58364] 2009-09-22 14:18:33.082 WARNING: bzr: warning: some compiled
> extensions could not be loaded; see
> <https://answers.launchpad.net/bzr/+faq/703>
>
>
> So it says "I can't load" but it doesn't say *what* fails to load, and
> with the shorter error, you don't show the summary of what failed to
> load either.
>
> -Derror doesn't seem to help.
>
> So I would recommend and least dropping the list of failures into the
> log file.

So I tried editing it myself, and that error message is all you get from
the exception. (ie, it doesn't tell you what plugin failed to load).

To get that info, we would have to actually add it to the api... :(

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkq4WfwACgkQJdeBCYSNAAO4agCfbmz3mRCWx722uX8IMmEBDCbt
XakAoIKkTQpW0whPZxvWpDXKbOAape5D
=S/ns
-----END PGP SIGNATURE-----

Revision history for this message
Martin Pool (mbp) wrote :

2009/9/22 John Arbash Meinel <email address hidden>:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> John A Meinel wrote:
>> Martin Pool wrote:
>>> Martin Pool has proposed merging lp:~mbp/bzr/406113-extension-warnings into lp:bzr.
>>
>>> Requested reviews:
>>>     bzr-core (bzr-core)
>>
>>> Here's an update for the bug 406113 taking into account John's comments in the previous review.
>>
>>> We now give just one warning, at the end of running bzr, describing all modules that failed to load.
>>
>>
>> So with this new version, I just started getting the failure on
>> Kerguelen. So I went to investigate, but I can't get any real info. This
>> is what is in .bzr.log:
>>
>> Tue 2009-09-22 14:18:26 +1000
>> 0.266  bzr arguments: [u'--version']
>> 0.406  encoding stdout as sys.stdout encoding 'cp437'
>> 0.641  failed to load compiled extension: DLL load failed: Access is denied.
>> 0.844  opening working tree 'C:/home/shared/bzr/bzr.dev'
>> 6.344  return code 0
>> [58364] 2009-09-22 14:18:33.082 WARNING: bzr: warning: some compiled
>> extensions could not be loaded; see
>> <https://answers.launchpad.net/bzr/+faq/703>
>>
>>
>> So it says "I can't load" but it doesn't say *what* fails to load, and
>> with the shorter error, you don't show the summary of what failed to
>> load either.
>>
>> -Derror doesn't seem to help.
>>
>> So I would recommend and least dropping the list of failures into the
>> log file.
>
> So I tried editing it myself, and that error message is all you get from
> the exception. (ie, it doesn't tell you what plugin failed to load).
>
> To get that info, we would have to actually add it to the api... :(

Do we even know which plugin is involved here?

It seems weird to me that a unix program would use the term "DLL", so
I suspect it's hardcoded in one of our plugins, and they're raising a
custom ImportError.

--
Martin <http://launchpad.net/~mbp/>

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

...

>>> So with this new version, I just started getting the failure on
>>> Kerguelen. So I went to investigate, but I can't get any real info. This
>>> is what is in .bzr.log:
>>>
>>> Tue 2009-09-22 14:18:26 +1000
>>> 0.266 bzr arguments: [u'--version']
>>> 0.406 encoding stdout as sys.stdout encoding 'cp437'
>>> 0.641 failed to load compiled extension: DLL load failed: Access is denied.
>>> 0.844 opening working tree 'C:/home/shared/bzr/bzr.dev'
>>> 6.344 return code 0
>>> [58364] 2009-09-22 14:18:33.082 WARNING: bzr: warning: some compiled
>>> extensions could not be loaded; see
>>> <https://answers.launchpad.net/bzr/+faq/703>
>>>
>>>
>>> So it says "I can't load" but it doesn't say *what* fails to load, and
>>> with the shorter error, you don't show the summary of what failed to
>>> load either.
>>>
>>> -Derror doesn't seem to help.
>>>
>>> So I would recommend and least dropping the list of failures into the
>>> log file.
>> So I tried editing it myself, and that error message is all you get from
>> the exception. (ie, it doesn't tell you what plugin failed to load).
>>
>> To get that info, we would have to actually add it to the api... :(
>
> Do we even know which plugin is involved here?
>
> It seems weird to me that a unix program would use the term "DLL", so
> I suspect it's hardcoded in one of our plugins, and they're raising a
> custom ImportError.

Well, this is on Windows, and it occurs even after I delete everything
and rebuild. I wonder if it is the _readdir_pyx issue, but I sort of
doubt it.

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkq4X+AACgkQJdeBCYSNAAO6YQCgix5Uw6p+EUh4+KMpALR15Qja
q/gAoL/CPIJuoeJ2OhzPxWJxie2JMiiy
=p4bA
-----END PGP SIGNATURE-----

Revision history for this message
Martin Pool (mbp) wrote :

2009/9/22 John Arbash Meinel <email address hidden>:
> Well, this is on Windows, and it occurs even after I delete everything
> and rebuild. I wonder if it is the _readdir_pyx issue, but I sort of
> doubt it.

My mistake.

I was assuming that the ImportError would always tell you what module
failed. Apparently not. If you file another bug, we can arrange for
the module name to be included in the message.

--
Martin <http://launchpad.net/~mbp/>

Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Pool wrote:
> 2009/9/22 John Arbash Meinel <email address hidden>:
>> Well, this is on Windows, and it occurs even after I delete everything
>> and rebuild. I wonder if it is the _readdir_pyx issue, but I sort of
>> doubt it.
>
> My mistake.
>
> I was assuming that the ImportError would always tell you what module
> failed. Apparently not. If you file another bug, we can arrange for
> the module name to be included in the message.
>
>

I managed to track it down to a failure to load _chk_map_pyx, and *that*
was actually because it was failing to import zlib1.dll.

By copying zlib1.dll into the bzrlib folder, and then changing the
permission bits, things worked again.

I did submit a bug request for making debugging extension failures
easier. On the plus side, this is exactly what your patch helps, since
before we just didn't know that things were failing.

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkq48psACgkQJdeBCYSNAAN11wCcD2hOqQRbs/gpVbnKUGGkpHWJ
++kAn2oGw3gxDXsfhNeA8UYEpgD+jSHY
=XpUz
-----END PGP SIGNATURE-----

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/__init__.py'
--- bzrlib/__init__.py 2009-07-20 11:27:05 +0000
+++ bzrlib/__init__.py 2009-07-29 03:08:32 +0000
@@ -55,6 +55,7 @@
55# API compatibility version: bzrlib is currently API compatible with 1.15.55# API compatibility version: bzrlib is currently API compatible with 1.15.
56api_minimum_version = (1, 17, 0)56api_minimum_version = (1, 17, 0)
5757
58
58def _format_version_tuple(version_info):59def _format_version_tuple(version_info):
59 """Turn a version number 2, 3 or 5-tuple into a short string.60 """Turn a version number 2, 3 or 5-tuple into a short string.
6061
6162
=== modified file 'bzrlib/annotate.py'
--- bzrlib/annotate.py 2009-07-08 17:09:03 +0000
+++ bzrlib/annotate.py 2009-09-11 06:36:50 +0000
@@ -454,5 +454,6 @@
454454
455try:455try:
456 from bzrlib._annotator_pyx import Annotator456 from bzrlib._annotator_pyx import Annotator
457except ImportError:457except ImportError, e:
458 osutils.failed_to_load_extension(e)
458 from bzrlib._annotator_py import Annotator459 from bzrlib._annotator_py import Annotator
459460
=== modified file 'bzrlib/bencode.py'
--- bzrlib/bencode.py 2009-06-03 14:14:31 +0000
+++ bzrlib/bencode.py 2009-09-11 06:36:50 +0000
@@ -16,7 +16,10 @@
1616
17"""Wrapper around the bencode pyrex and python implementation"""17"""Wrapper around the bencode pyrex and python implementation"""
1818
19from bzrlib import osutils
20
19try:21try:
20 from bzrlib._bencode_pyx import bdecode, bdecode_as_tuple, bencode, Bencached22 from bzrlib._bencode_pyx import bdecode, bdecode_as_tuple, bencode, Bencached
21except ImportError:23except ImportError, e:
24 osutils.failed_to_load_extension(e)
22 from bzrlib.util._bencode_py import bdecode, bdecode_as_tuple, bencode, Bencached25 from bzrlib.util._bencode_py import bdecode, bdecode_as_tuple, bencode, Bencached
2326
=== modified file 'bzrlib/btree_index.py'
--- bzrlib/btree_index.py 2009-07-01 10:51:47 +0000
+++ bzrlib/btree_index.py 2009-09-11 06:36:50 +0000
@@ -1385,5 +1385,6 @@
13851385
1386try:1386try:
1387 from bzrlib import _btree_serializer_pyx as _btree_serializer1387 from bzrlib import _btree_serializer_pyx as _btree_serializer
1388except ImportError:1388except ImportError, e:
1389 osutils.failed_to_load_extension(e)
1389 from bzrlib import _btree_serializer_py as _btree_serializer1390 from bzrlib import _btree_serializer_py as _btree_serializer
13901391
=== modified file 'bzrlib/chk_map.py'
--- bzrlib/chk_map.py 2009-07-16 23:28:49 +0000
+++ bzrlib/chk_map.py 2009-09-11 06:36:50 +0000
@@ -1637,7 +1637,8 @@
1637 _deserialise_leaf_node,1637 _deserialise_leaf_node,
1638 _deserialise_internal_node,1638 _deserialise_internal_node,
1639 )1639 )
1640except ImportError:1640except ImportError, e:
1641 osutils.failed_to_load_extension(e)
1641 from bzrlib._chk_map_py import (1642 from bzrlib._chk_map_py import (
1642 _search_key_16,1643 _search_key_16,
1643 _search_key_255,1644 _search_key_255,
16441645
=== modified file 'bzrlib/commands.py'
--- bzrlib/commands.py 2009-06-19 09:06:56 +0000
+++ bzrlib/commands.py 2009-09-11 06:42:23 +0000
@@ -1107,6 +1107,7 @@
1107 argv = new_argv1107 argv = new_argv
1108 ret = run_bzr_catch_errors(argv)1108 ret = run_bzr_catch_errors(argv)
1109 trace.mutter("return code %d", ret)1109 trace.mutter("return code %d", ret)
1110 osutils.report_extension_load_failures()
1110 return ret1111 return ret
11111112
11121113
11131114
=== modified file 'bzrlib/dirstate.py'
--- bzrlib/dirstate.py 2009-07-20 08:56:45 +0000
+++ bzrlib/dirstate.py 2009-09-11 06:36:50 +0000
@@ -3809,7 +3809,8 @@
3809 ProcessEntryC as _process_entry,3809 ProcessEntryC as _process_entry,
3810 update_entry as update_entry,3810 update_entry as update_entry,
3811 )3811 )
3812except ImportError:3812except ImportError, e:
3813 osutils.failed_to_load_extension(e)
3813 from bzrlib._dirstate_helpers_py import (3814 from bzrlib._dirstate_helpers_py import (
3814 _read_dirblocks,3815 _read_dirblocks,
3815 bisect_dirblock,3816 bisect_dirblock,
38163817
=== modified file 'bzrlib/graph.py'
--- bzrlib/graph.py 2009-06-12 18:05:15 +0000
+++ bzrlib/graph.py 2009-09-11 06:36:50 +0000
@@ -19,6 +19,7 @@
19from bzrlib import (19from bzrlib import (
20 debug,20 debug,
21 errors,21 errors,
22 osutils,
22 revision,23 revision,
23 trace,24 trace,
24 tsort,25 tsort,
@@ -1660,5 +1661,6 @@
1660_counters = [0,0,0,0,0,0,0]1661_counters = [0,0,0,0,0,0,0]
1661try:1662try:
1662 from bzrlib._known_graph_pyx import KnownGraph1663 from bzrlib._known_graph_pyx import KnownGraph
1663except ImportError:1664except ImportError, e:
1665 osutils.failed_to_load_extension(e)
1664 from bzrlib._known_graph_py import KnownGraph1666 from bzrlib._known_graph_py import KnownGraph
16651667
=== modified file 'bzrlib/groupcompress.py'
--- bzrlib/groupcompress.py 2009-07-06 20:21:34 +0000
+++ bzrlib/groupcompress.py 2009-09-11 06:36:50 +0000
@@ -1828,6 +1828,7 @@
1828 decode_base128_int,1828 decode_base128_int,
1829 )1829 )
1830 GroupCompressor = PyrexGroupCompressor1830 GroupCompressor = PyrexGroupCompressor
1831except ImportError:1831except ImportError, e:
1832 osutils.failed_to_load_extension(e)
1832 GroupCompressor = PythonGroupCompressor1833 GroupCompressor = PythonGroupCompressor
18331834
18341835
=== modified file 'bzrlib/knit.py'
--- bzrlib/knit.py 2009-07-28 08:09:13 +0000
+++ bzrlib/knit.py 2009-09-11 06:36:50 +0000
@@ -3622,5 +3622,6 @@
36223622
3623try:3623try:
3624 from bzrlib._knit_load_data_pyx import _load_data_c as _load_data3624 from bzrlib._knit_load_data_pyx import _load_data_c as _load_data
3625except ImportError:3625except ImportError, e:
3626 osutils.failed_to_load_extension(e)
3626 from bzrlib._knit_load_data_py import _load_data_py as _load_data3627 from bzrlib._knit_load_data_py import _load_data_py as _load_data
36273628
=== modified file 'bzrlib/osutils.py'
--- bzrlib/osutils.py 2009-07-23 16:01:17 +0000
+++ bzrlib/osutils.py 2009-09-11 06:39:56 +0000
@@ -21,6 +21,7 @@
21 S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)21 S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
22import sys22import sys
23import time23import time
24import warnings
2425
25from bzrlib.lazy_import import lazy_import26from bzrlib.lazy_import import lazy_import
26lazy_import(globals(), """27lazy_import(globals(), """
@@ -881,9 +882,56 @@
881 return parents882 return parents
882883
883884
885_extension_load_failures = []
886
887
888def failed_to_load_extension(exception):
889 """Handle failing to load a binary extension.
890
891 This should be called from the ImportError block guarding the attempt to
892 import the native extension. If this function returns, the pure-Python
893 implementation should be loaded instead::
894
895 >>> try:
896 >>> import bzrlib._fictional_extension_pyx
897 >>> except ImportError, e:
898 >>> bzrlib.osutils.failed_to_load_extension(e)
899 >>> import bzrlib._fictional_extension_py
900 """
901 # NB: This docstring is just an example, not a doctest, because doctest
902 # currently can't cope with the use of lazy imports in this namespace --
903 # mbp 20090729
904
905 # This currently doesn't report the failure at the time it occurs, because
906 # they tend to happen very early in startup when we can't check config
907 # files etc, and also we want to report all failures but not spam the user
908 # with 10 warnings.
909 from bzrlib import trace
910 exception_str = str(exception)
911 if exception_str not in _extension_load_failures:
912 trace.mutter("failed to load compiled extension: %s" % exception_str)
913 _extension_load_failures.append(exception_str)
914
915
916def report_extension_load_failures():
917 if not _extension_load_failures:
918 return
919 from bzrlib.config import GlobalConfig
920 if GlobalConfig().get_user_option_as_bool('ignore_missing_extensions'):
921 return
922 # the warnings framework should by default show this only once
923 warnings.warn(
924 "bzr: warning: Failed to load compiled extensions:\n"
925 " %s\n"
926 " Bazaar can run, but performance may be reduced.\n"
927 " Check Bazaar is correctly installed or set ignore_missing_extensions"
928 % '\n '.join(_extension_load_failures,))
929
930
884try:931try:
885 from bzrlib._chunks_to_lines_pyx import chunks_to_lines932 from bzrlib._chunks_to_lines_pyx import chunks_to_lines
886except ImportError:933except ImportError, e:
934 failed_to_load_extension(e)
887 from bzrlib._chunks_to_lines_py import chunks_to_lines935 from bzrlib._chunks_to_lines_py import chunks_to_lines
888936
889937
@@ -1466,7 +1514,8 @@
1466 try:1514 try:
1467 from bzrlib._readdir_pyx import UTF8DirReader1515 from bzrlib._readdir_pyx import UTF8DirReader
1468 _selected_dir_reader = UTF8DirReader()1516 _selected_dir_reader = UTF8DirReader()
1469 except ImportError:1517 except ImportError, e:
1518 failed_to_load_extension(e)
1470 pass1519 pass
14711520
1472 if _selected_dir_reader is None:1521 if _selected_dir_reader is None:
@@ -1778,7 +1827,8 @@
1778 try:1827 try:
1779 from bzrlib._readdir_pyx import UTF8DirReader1828 from bzrlib._readdir_pyx import UTF8DirReader
1780 file_kind_from_stat_mode = UTF8DirReader().kind_from_mode1829 file_kind_from_stat_mode = UTF8DirReader().kind_from_mode
1781 except ImportError:1830 except ImportError, e:
1831 failed_to_load_extension(e)
1782 from bzrlib._readdir_py import (1832 from bzrlib._readdir_py import (
1783 _kind_from_mode as file_kind_from_stat_mode1833 _kind_from_mode as file_kind_from_stat_mode
1784 )1834 )
17851835
=== modified file 'bzrlib/rio.py'
--- bzrlib/rio.py 2009-06-10 03:56:49 +0000
+++ bzrlib/rio.py 2009-09-11 06:36:50 +0000
@@ -32,6 +32,7 @@
3232
33import re33import re
3434
35from bzrlib import osutils
35from bzrlib.iterablefile import IterableFile36from bzrlib.iterablefile import IterableFile
3637
37# XXX: some redundancy is allowing to write stanzas in isolation as well as38# XXX: some redundancy is allowing to write stanzas in isolation as well as
@@ -377,7 +378,8 @@
377 _read_stanza_unicode,378 _read_stanza_unicode,
378 _valid_tag,379 _valid_tag,
379 )380 )
380except ImportError:381except ImportError, e:
382 osutils.failed_to_load_extension(e)
381 from bzrlib._rio_py import (383 from bzrlib._rio_py import (
382 _read_stanza_utf8,384 _read_stanza_utf8,
383 _read_stanza_unicode,385 _read_stanza_unicode,
384386
=== modified file 'bzrlib/tests/test_osutils.py'
--- bzrlib/tests/test_osutils.py 2009-07-23 16:01:17 +0000
+++ bzrlib/tests/test_osutils.py 2009-09-11 06:36:50 +0000
@@ -1798,3 +1798,33 @@
1798 def test_local_concurrency(self):1798 def test_local_concurrency(self):
1799 concurrency = osutils.local_concurrency()1799 concurrency = osutils.local_concurrency()
1800 self.assertIsInstance(concurrency, int)1800 self.assertIsInstance(concurrency, int)
1801
1802
1803class TestFailedToLoadExtension(tests.TestCase):
1804
1805 def _try_loading(self):
1806 try:
1807 import bzrlib._fictional_extension_py
1808 except ImportError, e:
1809 osutils.failed_to_load_extension(e)
1810 return True
1811
1812 def setUp(self):
1813 super(TestFailedToLoadExtension, self).setUp()
1814 self.saved_failures = osutils._extension_load_failures[:]
1815 del osutils._extension_load_failures[:]
1816 self.addCleanup(self.restore_failures)
1817
1818 def restore_failures(self):
1819 osutils._extension_load_failures = self.saved_failures
1820
1821 def test_failure_to_load(self):
1822 self._try_loading()
1823 self.assertLength(1, osutils._extension_load_failures)
1824 self.assertEquals(osutils._extension_load_failures[0],
1825 "No module named _fictional_extension_py")
1826
1827 def test_report_extension_load_failures(self):
1828 self.assertTrue(self._try_loading())
1829 warnings, result = self.callCatchWarnings(osutils.report_extension_load_failures)
1830 self.assertLength(1, warnings)