[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