[patch] remove scratch objects

Martin Pool mbp at canonical.com
Tue Jun 6 08:53:16 BST 2006


Some old doctests rely on special Scratch object which clean up
temporary directory when they're deleted.  This is a bit undesirable
because deletion is not predictable and the classes aren't used enough
to be worthwhile.  

 * Remove ScratchBranch, ScratchDir, ScratchTransport, etc
 * Remove old doctests or convert to unittests
 * Incidental cleanups

-- 
Martin
-------------- next part --------------
 HACKING                                                      |   15 ++
 NEWS                                                         |    6 +
 bzrlib/branch.py                                             |   43 -------
 bzrlib/bzrdir.py                                             |   66 -----------
 bzrlib/doc/api/__init__.py                                   |    4 
 bzrlib/doc/api/branch.txt                                    |   22 ++-
 bzrlib/store/text.py                                         |    4 
 bzrlib/tests/__init__.py                                     |   12 --
 bzrlib/tests/branch_implementations/test_branch.py           |   20 ---
 bzrlib/tests/test_whitebox.py                                |   18 ++-
 bzrlib/tests/workingtree_implementations/test_workingtree.py |   14 ++
 bzrlib/transport/local.py                                    |   17 --
 bzrlib/workingtree.py                                        |   13 --
 13 files changed, 73 insertions(+), 181 deletions(-)

=== modified file 'HACKING'
--- HACKING	
+++ HACKING	
@@ -267,6 +267,19 @@
     command changes it name or signature. Ideally only the tests for a
     given command are affected when a given command is changed.
 
+Doctests
+--------
+
+We make selective use of doctests__.  In general they should provide 
+*examples* within the API documentation which can incidentally be tested.  We 
+don't try to test every important case using doctests -- regular Python
+tests are generally a better solution.
+
+Most of these are in ``bzrlib/doc/api``.  More additions are welcome.
+
+  __ http://docs.python.org/lib/module-doctest.html
+
+
 Running tests
 =============
 Currently, bzr selftest is used to invoke tests.
@@ -387,4 +400,4 @@
 so, please reply and say so.)
 
 
-:: vim:tw=74:ai
+:: vim: ft=rst tw=74 ai

=== modified file 'NEWS'
--- NEWS	
+++ NEWS	
@@ -58,6 +58,12 @@
 
     * bzrlib.delta.compare_trees now iterates in alphabetically sorted order,
       rather than randomly walking the inventories. (John Arbash Meinel)
+
+  TESTING:
+
+    * Doctests are now run in temporary directories which are cleaned up when
+      they finish, rather than using special ScratchDir/ScratchBranch objects.
+      (Martin Pool)
 
 bzr 0.8.2  2006-05-17
   

=== modified file 'bzrlib/branch.py'
--- bzrlib/branch.py	
+++ bzrlib/branch.py	
@@ -300,32 +300,6 @@
         
         If self and other have not diverged, return a list of the revisions
         present in other, but missing from self.
-
-        >>> from bzrlib.workingtree import WorkingTree
-        >>> bzrlib.trace.silent = True
-        >>> d1 = bzrdir.ScratchDir()
-        >>> br1 = d1.open_branch()
-        >>> wt1 = d1.open_workingtree()
-        >>> d2 = bzrdir.ScratchDir()
-        >>> br2 = d2.open_branch()
-        >>> wt2 = d2.open_workingtree()
-        >>> br1.missing_revisions(br2)
-        []
-        >>> wt2.commit("lala!", rev_id="REVISION-ID-1")
-        >>> br1.missing_revisions(br2)
-        [u'REVISION-ID-1']
-        >>> br2.missing_revisions(br1)
-        []
-        >>> wt1.commit("lala!", rev_id="REVISION-ID-1")
-        >>> br1.missing_revisions(br2)
-        []
-        >>> wt2.commit("lala!", rev_id="REVISION-ID-2A")
-        >>> br1.missing_revisions(br2)
-        [u'REVISION-ID-2A']
-        >>> wt1.commit("lala!", rev_id="REVISION-ID-2B")
-        >>> br1.missing_revisions(br2)
-        Traceback (most recent call last):
-        DivergedBranches: These branches have diverged.  Try merge.
         """
         self_history = self.revision_history()
         self_len = len(self_history)
@@ -1332,20 +1306,3 @@
             new_test.id = make_new_test_id()
             result.addTest(new_test)
         return result
-
-
-######################################################################
-# predicates
-
-
- at deprecated_function(zero_eight)
-def ScratchBranch(*args, **kwargs):
-    """See bzrlib.bzrdir.ScratchDir."""
-    d = ScratchDir(*args, **kwargs)
-    return d.open_branch()
-
-
- at deprecated_function(zero_eight)
-def is_control_file(*args, **kwargs):
-    """See bzrlib.workingtree.is_control_file."""
-    return bzrlib.workingtree.is_control_file(*args, **kwargs)

=== modified file 'bzrlib/bzrdir.py'
--- bzrlib/bzrdir.py	
+++ bzrlib/bzrdir.py	
@@ -1307,72 +1307,6 @@
         return result
 
 
-class ScratchDir(BzrDir6):
-    """Special test class: a bzrdir that cleans up itself..
-
-    >>> d = ScratchDir()
-    >>> base = d.transport.base
-    >>> isdir(base)
-    True
-    >>> b.transport.__del__()
-    >>> isdir(base)
-    False
-    """
-
-    def __init__(self, files=[], dirs=[], transport=None):
-        """Make a test branch.
-
-        This creates a temporary directory and runs init-tree in it.
-
-        If any files are listed, they are created in the working copy.
-        """
-        if transport is None:
-            transport = bzrlib.transport.local.ScratchTransport()
-            # local import for scope restriction
-            BzrDirFormat6().initialize(transport.base)
-            super(ScratchDir, self).__init__(transport, BzrDirFormat6())
-            self.create_repository()
-            self.create_branch()
-            self.create_workingtree()
-        else:
-            super(ScratchDir, self).__init__(transport, BzrDirFormat6())
-
-        # BzrBranch creates a clone to .bzr and then forgets about the
-        # original transport. A ScratchTransport() deletes itself and
-        # everything underneath it when it goes away, so we need to
-        # grab a local copy to prevent that from happening
-        self._transport = transport
-
-        for d in dirs:
-            self._transport.mkdir(d)
-            
-        for f in files:
-            self._transport.put(f, 'content of %s' % f)
-
-    def clone(self):
-        """
-        >>> orig = ScratchDir(files=["file1", "file2"])
-        >>> os.listdir(orig.base)
-        [u'.bzr', u'file1', u'file2']
-        >>> clone = orig.clone()
-        >>> if os.name != 'nt':
-        ...   os.path.samefile(orig.base, clone.base)
-        ... else:
-        ...   orig.base == clone.base
-        ...
-        False
-        >>> os.listdir(clone.base)
-        [u'.bzr', u'file1', u'file2']
-        """
-        from shutil import copytree
-        from bzrlib.osutils import mkdtemp
-        base = mkdtemp()
-        os.rmdir(base)
-        copytree(self.base, base, symlinks=True)
-        return ScratchDir(
-            transport=bzrlib.transport.local.ScratchTransport(base))
-
-
 class Converter(object):
     """Converts a disk format object from one format to another."""
 

=== modified file 'bzrlib/doc/api/__init__.py'
--- bzrlib/doc/api/__init__.py	
+++ bzrlib/doc/api/__init__.py	
@@ -1,4 +1,4 @@
-# (C) 2005 Canonical Development Ltd
+# Copyright (C) 2005, 2006 Canonical Development 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
@@ -29,6 +29,6 @@
     
 def test_suite():
     candidates = os.listdir(os.path.dirname(__file__))
-    scripts = [candidate for candidate in candidates 
+    scripts = [candidate for candidate in candidates
                if candidate.endswith('.txt')]
     return doctest.DocFileSuite(*scripts)

=== modified file 'bzrlib/doc/api/branch.txt'
--- bzrlib/doc/api/branch.txt	
+++ bzrlib/doc/api/branch.txt	
@@ -2,28 +2,36 @@
 
 A Branch represents a series of commits and merges carried out by a user.
 
+Make a temporary directory for these tests:
+
+   >>> import tempfile
+   >>> test_dir = tempfile.mkdtemp(prefix='bzrlib_doc_api_branch_txt_')
+
 Branches are created by BzrDir's:
 
-   >>> from bzrlib.bzrdir import ScratchDir
    >>> from bzrlib.branch import Branch
-   >>> dir = ScratchDir()
-   >>> new_branch = dir.create_branch()
+   >>> from bzrlib.bzrdir import BzrDir
 
+   >>> new_branch = BzrDir.create_branch_convenience(test_dir)
 
 Existing Branches can be opened directly:
 
-   >>> another_instance = Branch.open(dir.transport.clone('..').base)
+   >>> transport = new_branch.bzrdir.transport
+   >>> another_instance = Branch.open(transport.clone('..').base)
 
 or via the BzrDir:
 
-   >>> still_the_same_branch = dir.open_branch()
-
+   >>> still_the_same_branch = new_branch.bzrdir.open_branch()
 
 A branch has a history of revisions on it:
 
    >>> new_branch.revision_history()
    []
 
-
 We need to write some more documentation, showing
 push and pull operations. Cloning might also be nice.
+
+And finally, clean up:
+
+   >>> import shutil
+   >>> shutil.rmtree(test_dir)

=== modified file 'bzrlib/store/text.py'
--- bzrlib/store/text.py	
+++ bzrlib/store/text.py	
@@ -120,7 +120,3 @@
             from cStringIO import StringIO
             sio = StringIO(f.read())
             return gzip.GzipFile(mode='rb', fileobj=sio)
-
-
-def ScratchTextStore():
-    return TextStore(ScratchTransport())

=== modified file 'bzrlib/tests/__init__.py'
--- bzrlib/tests/__init__.py	
+++ bzrlib/tests/__init__.py	
@@ -29,10 +29,12 @@
 import codecs
 from cStringIO import StringIO
 import difflib
+import doctest
 import errno
 import logging
 import os
 import re
+import shutil
 import stat
 import sys
 import tempfile
@@ -1109,11 +1111,7 @@
     This function can be replaced if you need to change the default test
     suite on a global basis, but it is not encouraged.
     """
-    from doctest import DocTestSuite
-
-    global MODULES_TO_DOCTEST
-
-    testmod_names = [ \
+    testmod_names = [
                    'bzrlib.tests.test_ancestry',
                    'bzrlib.tests.test_api',
                    'bzrlib.tests.test_bad_files',
@@ -1199,8 +1197,8 @@
         suite.addTest(package.test_suite())
     for m in MODULES_TO_TEST:
         suite.addTest(loader.loadTestsFromModule(m))
-    for m in (MODULES_TO_DOCTEST):
-        suite.addTest(DocTestSuite(m))
+    for m in MODULES_TO_DOCTEST:
+        suite.addTest(doctest.DocTestSuite(m))
     for name, plugin in bzrlib.plugin.all_plugins().items():
         if getattr(plugin, 'test_suite', None) is not None:
             suite.addTest(plugin.test_suite())

=== modified file 'bzrlib/tests/branch_implementations/test_branch.py'
--- bzrlib/tests/branch_implementations/test_branch.py	
+++ bzrlib/tests/branch_implementations/test_branch.py	
@@ -1,4 +1,4 @@
-# (C) 2005, 2006 Canonical Ltd
+# Copyright (C) 2005, 2006 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
@@ -341,24 +341,6 @@
         branch, relpath = Branch.open_containing(self.get_readonly_url('g/p/q'))
         self.assertEqual('g/p/q', relpath)
         
-# TODO: rewrite this as a regular unittest, without relying on the displayed output        
-#         >>> from bzrlib.commit import commit
-#         >>> bzrlib.trace.silent = True
-#         >>> br1 = ScratchBranch(files=['foo', 'bar'])
-#         >>> br1.working_tree().add('foo')
-#         >>> br1.working_tree().add('bar')
-#         >>> commit(br1, "lala!", rev_id="REVISION-ID-1", verbose=False)
-#         >>> br2 = ScratchBranch()
-#         >>> br2.update_revisions(br1)
-#         Added 2 texts.
-#         Added 1 inventories.
-#         Added 1 revisions.
-#         >>> br2.revision_history()
-#         [u'REVISION-ID-1']
-#         >>> br2.update_revisions(br1)
-#         Added 0 revisions.
-#         >>> br1.text_store.total_size() == br2.text_store.total_size()
-#         True
 
 class InstrumentedTransaction(object):
 

=== modified file 'bzrlib/tests/test_whitebox.py'
--- bzrlib/tests/test_whitebox.py	
+++ bzrlib/tests/test_whitebox.py	
@@ -1,8 +1,24 @@
+# Copyright (C) 2005, 2006 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
+
 import os
 import unittest
 
 from bzrlib.tests import TestCaseWithTransport, TestCase
-from bzrlib.branch import ScratchBranch, Branch
+from bzrlib.branch import Branch
 from bzrlib.errors import PathNotChild
 from bzrlib.osutils import relpath, pathjoin, abspath, realpath
 

=== modified file 'bzrlib/tests/workingtree_implementations/test_workingtree.py'
--- bzrlib/tests/workingtree_implementations/test_workingtree.py	
+++ bzrlib/tests/workingtree_implementations/test_workingtree.py	
@@ -150,10 +150,22 @@
         tree.revert(['hello.txt'])
         self.failUnlessExists('hello.txt')
 
-    def test_unknowns(self):
+    def test_unknowns_by_default_patterns(self):
+        """Backup files are ignored by default"""
         tree = self.make_branch_and_tree('.')
         self.build_tree(['hello.txt',
                          'hello.txt.~1~'])
+        self.assertEquals(list(tree.unknowns()),
+                          ['hello.txt'])
+
+    def test_versioned_files_not_unknown(self):
+        tree = self.make_branch_and_tree('.')
+        self.build_tree(['hello.txt',
+                         'hello.txt.~1~'])
+        tree.add('hello.txt')
+        self.assertEquals(list(tree.unknowns()),
+                          [])
+        tree.remove('hello.txt')
         self.assertEquals(list(tree.unknowns()),
                           ['hello.txt'])
 

=== modified file 'bzrlib/transport/local.py'
--- bzrlib/transport/local.py	
+++ bzrlib/transport/local.py	
@@ -281,23 +281,6 @@
             return True
 
 
-class ScratchTransport(LocalTransport):
-    """A transport that works in a temporary dir and cleans up after itself.
-    
-    The dir only exists for the lifetime of the Python object.
-    Obviously you should not put anything precious in it.
-    """
-
-    def __init__(self, base=None):
-        if base is None:
-            base = tempfile.mkdtemp()
-        super(ScratchTransport, self).__init__(base)
-
-    def __del__(self):
-        rmtree(self.base, ignore_errors=True)
-        mutter("%r destroyed" % self)
-
-
 class LocalRelpathServer(Server):
     """A pretend server for local transports, using relpaths."""
 

=== modified file 'bzrlib/workingtree.py'
--- bzrlib/workingtree.py	
+++ bzrlib/workingtree.py	
@@ -907,19 +907,6 @@
 
         These are files in the working directory that are not versioned or
         control files or ignored.
-        
-        >>> from bzrlib.bzrdir import ScratchDir
-        >>> d = ScratchDir(files=['foo', 'foo~'])
-        >>> b = d.open_branch()
-        >>> tree = d.open_workingtree()
-        >>> map(str, tree.unknowns())
-        ['foo']
-        >>> tree.add('foo')
-        >>> list(b.unknowns())
-        []
-        >>> tree.remove('foo')
-        >>> list(b.unknowns())
-        [u'foo']
         """
         for subp in self.extras():
             if not self.is_ignored(subp):



More information about the bazaar mailing list