Rev 2431: (John Arbash Meinel) 'make api-docs' will generate api documentation using epydoc. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Apr 19 23:03:20 BST 2007


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

------------------------------------------------------------
revno: 2431
revision-id: pqm at pqm.ubuntu.com-20070419220315-zw3uloe4se8laybs
parent: pqm at pqm.ubuntu.com-20070419213243-7s1gu2czd44bht1t
parent: john at arbash-meinel.com-20070417142905-3l0icevddeor3238
committer: Canonical.com Patch Queue Manager<pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2007-04-19 23:03:15 +0100
message:
  (John Arbash Meinel) 'make api-docs' will generate api documentation using epydoc.
removed:
  build-api                      build-api-20050309064830-a0be0dc1452cda87
added:
  tools/bzr_epydoc               bzr_epydoc-20070409231252-ec7uffstn62q7nhv-1
  tools/bzr_epydoc_uid.py        bzr_epydoc_uid.py-20070409231252-ec7uffstn62q7nhv-2
modified:
  .bzrignore                     bzrignore-20050311232317-81f7b71efa2db11a
  Makefile                       Makefile-20050805140406-d96e3498bb61c5bb
  bzrlib/lazy_import.py          lazy_import.py-20060910203832-f77c54gf3n232za0-1
  bzrlib/tests/test_lazy_import.py test_lazy_import.py-20060910203832-f77c54gf3n232za0-2
    ------------------------------------------------------------
    revno: 2413.4.2
    merged: john at arbash-meinel.com-20070417142905-3l0icevddeor3238
    parent: john at arbash-meinel.com-20070412202742-4cr2qmchdfe9mg7n
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: api-doc-builders
    timestamp: Tue 2007-04-17 09:29:05 -0500
    message:
      Remove the build-api script (as requested by Martin)
    ------------------------------------------------------------
    revno: 2413.4.1
    merged: john at arbash-meinel.com-20070412202742-4cr2qmchdfe9mg7n
    parent: pqm at pqm.ubuntu.com-20070412150356-jeie6iap22sae8xf
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: api-doc-builders
    timestamp: Thu 2007-04-12 15:27:42 -0500
    message:
      Cherrypick just the epydoc builder changes.
      This is just the piece of change that makes 'make api-docs' work,
      without any actual documentation changes.
=== removed file 'build-api'
--- a/build-api	2005-11-18 08:10:07 +0000
+++ b/build-api	1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-#!/bin/bash
-mkdir -p api
-PYTHONPATH=$PWD epydoc -o api/html --docformat restructuredtext bzr bzrlib

=== added file 'tools/bzr_epydoc'
--- a/tools/bzr_epydoc	1970-01-01 00:00:00 +0000
+++ b/tools/bzr_epydoc	2007-04-12 20:27:42 +0000
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+#
+# Call the command line interface for Epydoc.
+#
+
+"""Wrapper around Epydoc that just makes it understand bzr's lazy imports."""
+
+# This will enable the lazy_import compatibility code
+import bzr_epydoc_uid
+
+from epydoc.cli import cli
+cli()
+
+

=== added file 'tools/bzr_epydoc_uid.py'
--- a/tools/bzr_epydoc_uid.py	1970-01-01 00:00:00 +0000
+++ b/tools/bzr_epydoc_uid.py	2007-04-12 20:27:42 +0000
@@ -0,0 +1,43 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Monkey patch to make epydoc work with bzrlib's lazy imports."""
+
+import epydoc.uid
+
+import bzrlib.lazy_import
+
+
+_ObjectUID = epydoc.uid.ObjectUID
+_ScopeReplacer = bzrlib.lazy_import.ScopeReplacer
+
+
+class ObjectUID(_ObjectUID):
+
+    def __init__(self, obj):
+        if isinstance(obj, _ScopeReplacer):
+            # The isinstance will trigger a replacement if it is a real
+            # _BzrScopeReplacer, but the local object won't know about it, so
+            # replace it locally.
+            obj = object.__getattribute__(obj, '_real_obj')
+        _ObjectUID.__init__(self, obj)
+
+
+epydoc.uid.ObjectUID = ObjectUID
+
+
+_ScopeReplacer._should_proxy = True
+

=== modified file '.bzrignore'
--- a/.bzrignore	2006-11-10 01:55:55 +0000
+++ b/.bzrignore	2007-04-12 20:27:42 +0000
@@ -33,3 +33,4 @@
 ./.perf_history
 ./html_docs
 ./pretty_docs
+./api

=== modified file 'Makefile'
--- a/Makefile	2007-04-19 02:27:44 +0000
+++ b/Makefile	2007-04-19 22:03:15 +0000
@@ -1,3 +1,25 @@
+# Copyright (C) 2005, 2006, 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+# A relatively simple Makefile to assist in building parts of bzr. Mostly for
+# building documentation, etc.
+
+.PHONY: all clean pyflakes api-docs
+
+
 all:
 
 check:
@@ -23,7 +45,13 @@
 	-find . -name "*.pyc" -o -name "*.pyo" | xargs rm -f
 	rm -rf test????.tmp
 
-.PHONY: all
+docfiles = bzr bzrlib
+api-docs:
+	mkdir -p api/html
+	PYTHONPATH=$(PWD) python tools/bzr_epydoc --html -o api/html --docformat 'restructuredtext en' $(docfiles)
+
+check-api-docs:
+	PYTHONPATH=$(PWD) python tools/bzr_epydoc --check --docformat 'restructuredtext en' $(docfiles)
 
 
 # build emacs cross-reference

=== modified file 'bzrlib/lazy_import.py'
--- a/bzrlib/lazy_import.py	2006-10-16 01:25:46 +0000
+++ b/bzrlib/lazy_import.py	2007-04-12 20:27:42 +0000
@@ -48,7 +48,12 @@
     needed.
     """
 
-    __slots__ = ('_scope', '_factory', '_name')
+    __slots__ = ('_scope', '_factory', '_name', '_real_obj')
+
+    # Setting this to True will allow you to do x = y, and still access members
+    # from both variables. This should not normally be enabled, but is useful
+    # when building documentation.
+    _should_proxy = False
 
     def __init__(self, scope, factory, name):
         """Create a temporary object in the specified scope.
@@ -62,6 +67,7 @@
         self._scope = scope
         self._factory = factory
         self._name = name
+        self._real_obj = None
         scope[name] = self
 
     def _replace(self):
@@ -81,6 +87,8 @@
                           " to another variable?",
                 extra=e)
         obj = factory(self, scope, name)
+        if ScopeReplacer._should_proxy:
+            self._real_obj = obj
         scope[name] = obj
         return obj
 
@@ -92,10 +100,12 @@
         # del self._name
 
     def __getattribute__(self, attr):
-        _replace = object.__getattribute__(self, '_replace')
-        obj = _replace()
-        _cleanup = object.__getattribute__(self, '_cleanup')
-        _cleanup()
+        obj = object.__getattribute__(self, '_real_obj')
+        if obj is None:
+            _replace = object.__getattribute__(self, '_replace')
+            obj = _replace()
+            _cleanup = object.__getattribute__(self, '_cleanup')
+            _cleanup()
         return getattr(obj, attr)
 
     def __call__(self, *args, **kwargs):

=== modified file 'bzrlib/tests/test_lazy_import.py'
--- a/bzrlib/tests/test_lazy_import.py	2006-10-11 23:08:27 +0000
+++ b/bzrlib/tests/test_lazy_import.py	2007-04-12 20:27:42 +0000
@@ -96,6 +96,15 @@
     get collisions.
     """
 
+    def setUp(self):
+        TestCase.setUp(self)
+        # These tests assume we will not be proxying, so make sure proxying is
+        # disabled.
+        orig_proxy = lazy_import.ScopeReplacer._should_proxy
+        def restore():
+            lazy_import.ScopeReplacer._should_proxy = orig_proxy
+        lazy_import.ScopeReplacer._should_proxy = False
+
     def test_object(self):
         """ScopeReplacer can create an instance in local scope.
         
@@ -326,16 +335,74 @@
         self.assertRaises(errors.IllegalUseOfScopeReplacer,
                           getattr, test_obj3, 'foo')
         
-        # However, the 
-        self.assertEqual([('__getattribute__', 'foo'),
-                          '_replace',
-                          'factory',
-                          'init',
-                          ('foo', 1),
-                          ('foo', 2),
-                          ('foo', 3),
-                          ('__getattribute__', 'foo'),
-                          '_replace',
+        self.assertEqual([('__getattribute__', 'foo'),
+                          '_replace',
+                          'factory',
+                          'init',
+                          ('foo', 1),
+                          ('foo', 2),
+                          ('foo', 3),
+                          ('__getattribute__', 'foo'),
+                          '_replace',
+                         ], actions)
+
+    def test_enable_proxying(self):
+        """Test that we can allow ScopeReplacer to proxy."""
+        actions = []
+        InstrumentedReplacer.use_actions(actions)
+        TestClass.use_actions(actions)
+
+        def factory(replacer, scope, name):
+            actions.append('factory')
+            return TestClass()
+
+        try:
+            test_obj4
+        except NameError:
+            # test_obj4 shouldn't exist yet
+            pass
+        else:
+            self.fail('test_obj4 was not supposed to exist yet')
+
+        lazy_import.ScopeReplacer._should_proxy = True
+        InstrumentedReplacer(scope=globals(), name='test_obj4',
+                             factory=factory)
+
+        self.assertEqual(InstrumentedReplacer,
+                         object.__getattribute__(test_obj4, '__class__'))
+        test_obj5 = test_obj4
+        self.assertEqual(InstrumentedReplacer,
+                         object.__getattribute__(test_obj4, '__class__'))
+        self.assertEqual(InstrumentedReplacer,
+                         object.__getattribute__(test_obj5, '__class__'))
+
+        # The first use of the alternate variable causes test_obj2 to
+        # be replaced.
+        self.assertEqual('foo', test_obj4.foo(1))
+        self.assertEqual(TestClass,
+                         object.__getattribute__(test_obj4, '__class__'))
+        self.assertEqual(InstrumentedReplacer,
+                         object.__getattribute__(test_obj5, '__class__'))
+        # We should be able to access test_obj4 attributes normally
+        self.assertEqual('foo', test_obj4.foo(2))
+        # because we enabled proxying, test_obj5 can access its members as well
+        self.assertEqual('foo', test_obj5.foo(3))
+        self.assertEqual('foo', test_obj5.foo(4))
+
+        # However, it cannot be replaced by the ScopeReplacer
+        self.assertEqual(InstrumentedReplacer,
+                         object.__getattribute__(test_obj5, '__class__'))
+
+        self.assertEqual([('__getattribute__', 'foo'),
+                          '_replace',
+                          'factory',
+                          'init',
+                          ('foo', 1),
+                          ('foo', 2),
+                          ('__getattribute__', 'foo'),
+                          ('foo', 3),
+                          ('__getattribute__', 'foo'),
+                          ('foo', 4),
                          ], actions)
 
 




More information about the bazaar-commits mailing list