Rev 2326: First set of tests for path_info working - unicode, native paths, missing paths, and pack_stat results. in file:///home/robertc/source/baz/dirstate2/

Robert Collins robertc at robertcollins.net
Fri Mar 9 06:16:10 GMT 2007


At file:///home/robertc/source/baz/dirstate2/

------------------------------------------------------------
revno: 2326
revision-id: robertc at robertcollins.net-20070309061608-pau0d6iy2rss65lg
parent: robertc at robertcollins.net-20070309042352-6gabe2550go95z2d
committer: Robert Collins <robertc at robertcollins.net>
branch nick: dirstate2
timestamp: Fri 2007-03-09 17:16:08 +1100
message:
  First set of tests for path_info working - unicode, native paths, missing paths, and pack_stat results.
modified:
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/path_info.py            path_info.py-20070309041626-f8val8ukxzzzyudi-1
  bzrlib/path_info_python.py     path_info_python.py-20070309041626-f8val8ukxzzzyudi-2
  bzrlib/tests/path_info_implementations/test_path_info.py test_path_info.py-20070309041626-f8val8ukxzzzyudi-5
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2007-03-07 01:14:11 +0000
+++ b/bzrlib/osutils.py	2007-03-09 06:16:08 +0000
@@ -102,28 +102,7 @@
         return f
 
 
-_directory_kind = 'directory'
-
-_formats = {
-    stat.S_IFDIR:_directory_kind,
-    stat.S_IFCHR:'chardev',
-    stat.S_IFBLK:'block',
-    stat.S_IFREG:'file',
-    stat.S_IFIFO:'fifo',
-    stat.S_IFLNK:'symlink',
-    stat.S_IFSOCK:'socket',
-}
-
-
-def file_kind_from_stat_mode(stat_mode, _formats=_formats, _unknown='unknown'):
-    """Generate a file kind from a stat mode. This is used in walkdirs.
-
-    Its performance is critical: Do not mutate without careful benchmarking.
-    """
-    try:
-        return _formats[stat_mode & 0170000]
-    except KeyError:
-        return _unknown
+from path_info import _directory_kind, _formats, file_kind_from_stat_mode
 
 
 def file_kind(f, _lstat=os.lstat, _mapper=file_kind_from_stat_mode):

=== modified file 'bzrlib/path_info.py'
--- a/bzrlib/path_info.py	2007-03-09 04:23:52 +0000
+++ b/bzrlib/path_info.py	2007-03-09 06:16:08 +0000
@@ -16,9 +16,51 @@
 
 """Functions for accessing data about paths."""
 
-from path_info_python import *
+__all__ = ['kind_file', 'kind_missing', 'pack_stat', 'path_info']
+
+import stat
 
 def _test_modules():
     import bzrlib.path_info_python
-    # todo, look for the C module.
-    return [bzrlib.path_info_python]
+    result = [bzrlib.path_info_python]
+    try:
+        import bzrlib.path_info_c
+        result.append(bzrlib.path_info_c)
+    except ImportError:
+        pass
+    return result
+
+
+# singletons for talking about kinds. These should not be replaced
+# by implementation modules; even though its possible to do so.
+kind_file = 'file'
+kind_missing = 'missing'
+_directory_kind = 'directory'
+
+_formats = {
+    stat.S_IFDIR:_directory_kind,
+    stat.S_IFCHR:'chardev',
+    stat.S_IFBLK:'block',
+    stat.S_IFREG:kind_file,
+    stat.S_IFIFO:'fifo',
+    stat.S_IFLNK:'symlink',
+    stat.S_IFSOCK:'socket',
+}
+
+
+def file_kind_from_stat_mode(stat_mode, _formats=_formats, _unknown='unknown'):
+    """Generate a file kind from a stat mode. This is used in walkdirs.
+
+    Its performance is critical: Do not mutate without careful benchmarking.
+    """
+    try:
+        return _formats[stat_mode & 0170000]
+    except KeyError:
+        return _unknown
+
+
+# at the end to avoid circular import issues
+try:
+    from bzrlib.path_info_c import *
+except ImportError:
+    from bzrlib.path_info_python import *

=== modified file 'bzrlib/path_info_python.py'
--- a/bzrlib/path_info_python.py	2007-03-09 04:23:52 +0000
+++ b/bzrlib/path_info_python.py	2007-03-09 06:16:08 +0000
@@ -19,10 +19,19 @@
 This is the pure python implementation.
 """
 
-__all__ = ['pack_stat']
+__all__ = ['pack_stat', 'path_info']
 
 import base64
+import errno
+import os
+import stat
 import struct
+import sys
+
+# import from the imported path_info module, which has not yet been assigned
+# into bzrlib.
+file_kind_from_stat_mode = sys.modules['bzrlib.path_info'].file_kind_from_stat_mode
+kind_missing = sys.modules['bzrlib.path_info'].kind_missing
 
 
 def pack_stat(st, _encode=base64.encodestring, _pack=struct.pack):
@@ -37,3 +46,20 @@
     return _encode(_pack('>llllll'
         , st.st_size, int(st.st_mtime), int(st.st_ctime)
         , st.st_dev, st.st_ino, st.st_mode))[:-1]
+
+
+def path_info(abspath, _lstat=os.lstat, _mapper=file_kind_from_stat_mode,
+    _S_IEXEC=stat.S_IEXEC, _ENOENT=errno.ENOENT, _kind_missing=kind_missing):
+    """Get the kind, size, executability and statcache key for abspath."""
+    assert abspath.__class__ == str
+    try:
+        st = _lstat(abspath)
+    except OSError, e:
+        if e.errno != _ENOENT:
+            raise
+        else:
+            # TODO: could make this a constant to return, if we expect it to be
+            # common.
+            return (_kind_missing, 0, False, '')
+    return (_mapper(st.st_mode), st.st_size, bool(_S_IEXEC & st.st_mode),
+        pack_stat(st))

=== modified file 'bzrlib/tests/path_info_implementations/test_path_info.py'
--- a/bzrlib/tests/path_info_implementations/test_path_info.py	2007-03-09 04:23:52 +0000
+++ b/bzrlib/tests/path_info_implementations/test_path_info.py	2007-03-09 06:16:08 +0000
@@ -16,18 +16,67 @@
 
 """This tests the most primitive path_info call - path_info(abspath)."""
 
-import os
+import os.path
+import stat
+import sys
 
+from bzrlib import osutils
+from bzrlib.path_info import *
 from bzrlib.tests import TestCaseInTempDir
 
 
 class TestPathInfo(TestCaseInTempDir):
 
-    def disabled_test_info_file_non_utf8(self):
+    def test_info_file_non_utf8(self):
         # a simple non-utf, non-executable test that should pass on all
         # platforms.
         self.build_tree(['file'])
-        result = self.path_info.path_info(os.abspath('file'))
-        stat = os.lstat(result)
-        expected = ('file')
-        self.assertEqual(expected, result)
+        result = self.path_info.path_info(os.path.abspath('file'))
+        stat = os.lstat('file')
+        expected = ('file', stat.st_size, False, pack_stat(stat))
+        self.assertEqual(expected, result)
+        self.assertIs(kind_file, result[0])
+
+    def test_info_file_non_utf8_executable(self):
+        if not osutils.supports_executable():
+            raise TestSkipped('platform does support executable bits.')
+        # a simple non-utf, executable test that should pass on all
+        # platforms supporting executable bits.
+        self.build_tree(['file'])
+        st = os.lstat('file')
+        # make the file executable for this user
+        os.chmod('file', st.st_mode | stat.S_IXUSR)
+        st = os.lstat('file')
+        result = self.path_info.path_info(os.path.abspath('file'))
+        expected = ('file', st.st_size, True, pack_stat(st))
+        self.assertEqual(expected, result)
+        self.assertIs(kind_file, result[0])
+
+    def test_info_file_unicode(self):
+        # path_info should assert when asked for unicode paths.
+        self.assertRaises(AssertionError, self.path_info.path_info, u'foo')
+
+    def test_info_file_native(self):
+        # a non-executable test for all unicode supporting platforms.
+        # path_info expects to be called with a bytestring that is ready to
+        # hand to the os: this is to make C replacements easier.
+        try:
+            self.build_tree([u'\xe8file'])
+        except UnicodeEncodeError:
+            # not applicable on this platform.
+            return
+        encoding = sys.getfilesystemencoding()
+        encoded_name = u'\xe8file'.encode(encoding)
+        result = self.path_info.path_info(os.path.abspath(encoded_name))
+        stat = os.lstat(encoded_name)
+        expected = ('file', stat.st_size, False, pack_stat(stat))
+        self.assertEqual(expected, result)
+        self.assertIs(kind_file, result[0])
+
+    def test_info_absent_path(self):
+        # path_info should return a canned 'missing' kind for paths that are not
+        # present on disk.
+        result = self.path_info.path_info(os.path.abspath('missing-file'))
+        expected = ('missing', 0, False, '')
+        self.assertEqual(expected, result)
+        self.assertIs(kind_missing, result[0])



More information about the bazaar-commits mailing list