Rev 5308: (lifeless) A lazy-load support glue for Branch formats. (Robert Collins) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Sun Jun 20 23:36:29 BST 2010
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5308 [merge]
revision-id: pqm at pqm.ubuntu.com-20100620223626-sa26emhs7rjpba4h
parent: pqm at pqm.ubuntu.com-20100618115713-5d0yqkzo14eu94t4
parent: robertc at robertcollins.net-20100620211449-9ns38l9zvdxd1n96
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Sun 2010-06-20 23:36:26 +0100
message:
(lifeless) A lazy-load support glue for Branch formats. (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/branch.py branch.py-20050309040759-e4baf4e0d046576e
bzrlib/tests/per_branch/__init__.py __init__.py-20060123013057-b12a52c3f361daf4
bzrlib/tests/test_branch.py test_branch.py-20060116013032-97819aa07b8ab3b5
=== modified file 'NEWS'
--- a/NEWS 2010-06-18 11:57:13 +0000
+++ b/NEWS 2010-06-20 22:36:26 +0000
@@ -92,6 +92,12 @@
plugins to intercept this even when a ``RemoteBranch`` proxy is in use.
(Robert Collins, #201613)
+* ``Branch`` formats can now be loaded lazily by registering a
+ ``MetaDirBranchFormatFactory`` rather than an actual format. This will
+ cause the named format class to be loaded only when an enumeration of
+ formats is needed or when the format string for the object is
+ encountered. (Robert Collins, Jelmer Vernooij)
+
* Use lazy imports in ``bzrlib/merge.py`` so that plugins like ``news_merge``
do not cause modules to be loaded unnecessarily just because the plugin
registers a merge hook. This improves ``bzr rocks`` time by about 25%
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py 2010-06-17 06:30:22 +0000
+++ b/bzrlib/branch.py 2010-06-20 21:14:49 +0000
@@ -1518,7 +1518,10 @@
try:
transport = a_bzrdir.get_branch_transport(None, name=name)
format_string = transport.get_bytes("format")
- return klass._formats[format_string]
+ format = klass._formats[format_string]
+ if isinstance(format, MetaDirBranchFormatFactory):
+ return format()
+ return format
except errors.NoSuchFile:
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
except KeyError:
@@ -1529,6 +1532,20 @@
"""Return the current default format."""
return klass._default_format
+ @classmethod
+ def get_formats(klass):
+ """Get all the known formats.
+
+ Warning: This triggers a load of all lazy registered formats: do not
+ use except when that is desireed.
+ """
+ result = []
+ for fmt in klass._formats.values():
+ if isinstance(fmt, MetaDirBranchFormatFactory):
+ fmt = fmt()
+ result.append(fmt)
+ return result
+
def get_reference(self, a_bzrdir, name=None):
"""Get the target reference of the branch in a_bzrdir.
@@ -1671,11 +1688,19 @@
@classmethod
def register_format(klass, format):
- """Register a metadir format."""
+ """Register a metadir format.
+
+ See MetaDirBranchFormatFactory for the ability to register a format
+ without loading the code the format needs until it is actually used.
+ """
klass._formats[format.get_format_string()] = format
# Metadir formats have a network name of their format string, and get
- # registered as class factories.
- network_format_registry.register(format.get_format_string(), format.__class__)
+ # registered as factories.
+ if isinstance(format, MetaDirBranchFormatFactory):
+ network_format_registry.register(format.get_format_string(), format)
+ else:
+ network_format_registry.register(format.get_format_string(),
+ format.__class__)
@classmethod
def set_default_format(klass, format):
@@ -1701,6 +1726,34 @@
return False # by default
+class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
+ """A factory for a BranchFormat object, permitting simple lazy registration.
+
+ While none of the built in BranchFormats are lazy registered yet,
+ bzrlib.tests.test_branch.TestMetaDirBranchFormatFactory demonstrates how to
+ use it, and the bzr-loom plugin uses it as well (see
+ bzrlib.plugins.loom.formats).
+ """
+
+ def __init__(self, format_string, module_name, member_name):
+ """Create a MetaDirBranchFormatFactory.
+
+ :param format_string: The format string the format has.
+ :param module_name: Module to load the format class from.
+ :param member_name: Attribute name within the module for the format class.
+ """
+ registry._LazyObjectGetter.__init__(self, module_name, member_name)
+ self._format_string = format_string
+
+ def get_format_string(self):
+ """See BranchFormat.get_format_string."""
+ return self._format_string
+
+ def __call__(self):
+ """Used for network_format_registry support."""
+ return self.get_obj()()
+
+
class BranchHooks(Hooks):
"""A dictionary mapping hook name to a list of callables for branch hooks.
=== modified file 'bzrlib/tests/per_branch/__init__.py'
--- a/bzrlib/tests/per_branch/__init__.py 2010-05-13 15:14:41 +0000
+++ b/bzrlib/tests/per_branch/__init__.py 2010-06-18 04:37:50 +0000
@@ -132,7 +132,7 @@
# Generate a list of branch formats and their associated bzrdir formats to
# use.
combinations = [(format, format._matchingbzrdir) for format in
- BranchFormat._formats.values() + _legacy_formats]
+ BranchFormat.get_formats() + _legacy_formats]
scenarios = make_scenarios(
# None here will cause the default vfs transport server to be used.
None,
=== modified file 'bzrlib/tests/test_branch.py'
--- a/bzrlib/tests/test_branch.py 2010-04-23 07:15:23 +0000
+++ b/bzrlib/tests/test_branch.py 2010-06-20 21:14:49 +0000
@@ -136,6 +136,27 @@
return "opened branch."
+# Demonstrating how lazy loading is often implemented:
+# A constant string is created.
+SampleSupportedBranchFormatString = "Sample supported branch format."
+
+# And the format class can then reference the constant to avoid skew.
+class SampleSupportedBranchFormat(_mod_branch.BranchFormat):
+ """A sample supported format."""
+
+ def get_format_string(self):
+ """See BzrBranchFormat.get_format_string()."""
+ return SampleSupportedBranchFormatString
+
+ def initialize(self, a_bzrdir, name=None):
+ t = a_bzrdir.get_branch_transport(self, name=name)
+ t.put_bytes('format', self.get_format_string())
+ return 'A branch'
+
+ def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
+ return "opened supported branch."
+
+
class TestBzrBranchFormat(tests.TestCaseWithTransport):
"""Tests for the BzrBranchFormat facility."""
@@ -152,6 +173,17 @@
self.failUnless(isinstance(found_format, format.__class__))
check_format(_mod_branch.BzrBranchFormat5(), "bar")
+ def test_find_format_factory(self):
+ dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
+ SampleSupportedBranchFormat().initialize(dir)
+ factory = _mod_branch.MetaDirBranchFormatFactory(
+ SampleSupportedBranchFormatString,
+ "bzrlib.tests.test_branch", "SampleSupportedBranchFormat")
+ _mod_branch.BranchFormat.register_format(factory)
+ self.addCleanup(_mod_branch.BranchFormat.unregister_format, factory)
+ b = _mod_branch.Branch.open(self.get_url())
+ self.assertEqual(b, "opened supported branch.")
+
def test_find_format_not_branch(self):
dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
self.assertRaises(errors.NotBranchError,
@@ -186,6 +218,34 @@
self.make_branch_and_tree('bar')
+#Used by TestMetaDirBranchFormatFactory
+FakeLazyFormat = None
+
+
+class TestMetaDirBranchFormatFactory(tests.TestCase):
+
+ def test_get_format_string_does_not_load(self):
+ """Formats have a static format string."""
+ factory = _mod_branch.MetaDirBranchFormatFactory("yo", None, None)
+ self.assertEqual("yo", factory.get_format_string())
+
+ def test_call_loads(self):
+ # __call__ is used by the network_format_registry interface to get a
+ # Format.
+ global FakeLazyFormat
+ del FakeLazyFormat
+ factory = _mod_branch.MetaDirBranchFormatFactory(None,
+ "bzrlib.tests.test_branch", "FakeLazyFormat")
+ self.assertRaises(AttributeError, factory)
+
+ def test_call_returns_call_of_referenced_object(self):
+ global FakeLazyFormat
+ FakeLazyFormat = lambda:'called'
+ factory = _mod_branch.MetaDirBranchFormatFactory(None,
+ "bzrlib.tests.test_branch", "FakeLazyFormat")
+ self.assertEqual('called', factory())
+
+
class TestBranch67(object):
"""Common tests for both branch 6 and 7 which are mostly the same."""
More information about the bazaar-commits
mailing list