[Patches] New lib module: UserString.py and testcase for it

Peter Funk pf@artcom-gmbh.de
Mon, 3 Apr 2000 00:58:04 +0200 (MEST)


Dear Python patcher!

Please add the files appended below and commit them into the CVS tree.
(Note: the patch submission guide lines are not very clear about the 
 mail format for a suite of new module files.  I've used good old 'shar'.  
 Please tell me if I should submit a context diff against null or a 
 set of mime attachments instead.)
--=-- argument: --=--=--=--=--=--=--=--=--=--=-->8--=-
In Python 1.6 string objects have grown a bunch of methods.
Users may wish to override particular methods in self defined classes.
UserString wraps builtin string objects into a wrapper class similar 
to UserDict and UserList.  UserString object instances are still immutable.
For educational purposes a class `MutableString' derived from `UserString'
is also provided.
--=-- obligatory disclaimer: -=--=--=--=--=--=-->8--=-
I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.
--=-- dry signature: =--=--=--=--=--=--=--=--=-->8--=-
note: In order to fullfil the formal requirements I have submitted
      the wet signature form per postal mail.  This should arrive at your
      site in a week or so (I've applied air mail postage).

Regards, Peter
-- 
Peter Funk, Oldenburger Str.86, D-27777 Ganderkesee, Germany, Fax:+49 4222950260
office: +49 421 20419-0 (ArtCom GmbH, Grazer Str.8, D-28359 Bremen)
--=-- shar file: --=--=--=--=--=--=--=--=--=--=--=-->8--=-
#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2c).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2000-04-03 00:53 MEST by <pf@artcom0>.
# Source directory was `/home/pf/archiv/freeware/python/CVS_01_04_00/dist'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#   7077 -rwxrwxr-x src/Lib/UserString.py
#   6599 -rwxrwxr-x src/Lib/test/test_userstring.py
#     16 -rw-rw---- src/Lib/test/output/test_userstring
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    shar_n= shar_c='
'
  else
    shar_n=-n shar_c=
  fi
else
  shar_n= shar_c='\c'
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
$echo $shar_n 'x -' 'lock directory' "\`_sh29194': "$shar_c
if mkdir _sh29194; then
  $echo 'created'
else
  $echo 'failed to create'
  exit 1
fi
# ============= src/Lib/UserString.py ==============
if test ! -d 'src'; then
  $echo $echo_n 'x -' 'src: '$echo_c
  if mkdir 'src'; then $echo 'created'; else $echo 'failed to create'; fi
fi
if test ! -d 'src/Lib'; then
  $echo $echo_n 'x -' 'src/Lib: '$echo_c
  if mkdir 'src/Lib'; then $echo 'created'; else $echo 'failed to create'; fi
fi
if test -f 'src/Lib/UserString.py' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'src/Lib/UserString.py' '(file already exists)'
else
  $echo 'x -' extracting 'src/Lib/UserString.py' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/Lib/UserString.py' &&
#!/usr/bin/env python
## vim:ts=4:et:nowrap
"""A user-defined wrapper around string objects
X
Note: string objects have grown methods in Python 1.6 
This module requires Python 1.6 or later.
"""
from types import StringType, UnicodeType
import sys
X
class UserString:
X    def __init__(self, seq):
X        if isinstance(seq, StringType) or isinstance(seq, UnicodeType):
X            self.data = seq
X        elif isinstance(seq, UserString):
X            self.data = seq.data[:]
X        else: 
X            self.data = str(seq)
X    def __str__(self): return str(self.data)
X    def __repr__(self): return repr(self.data)
X    def __int__(self): return int(self.data)
X    def __long__(self): return long(self.data)
X    def __float__(self): return float(self.data)
X    def __complex__(self): return complex(self.data)
X    def __hash__(self): return hash(self.data)
X
X    def __cmp__(self, string):
X        if isinstance(string, UserString):
X            return cmp(self.data, string.data)
X        else:
X            return cmp(self.data, string)
X    def __contains__(self, char):
X        return char in self.data
X
X    def __len__(self): return len(self.data)
X    def __getitem__(self, index): return self.__class__(self.data[index])
X    def __getslice__(self, start, end):
X        start = max(start, 0); end = max(end, 0)
X        return self.__class__(self.data[start:end])
X
X    def __add__(self, other):
X        if isinstance(other, UserString):
X            return self.__class__(self.data + other.data)
X        elif isinstance(other, StringType) or isinstance(other, UnicodeType):
X            return self.__class__(self.data + other)
X        else:
X            return self.__class__(self.data + str(other))
X    def __radd__(self, other):
X        if isinstance(other, StringType) or isinstance(other, UnicodeType):
X            return self.__class__(other + self.data)
X        else:
X            return self.__class__(str(other) + self.data)
X    def __mul__(self, n):
X        return self.__class__(self.data*n)
X    __rmul__ = __mul__
X
X    # the following methods are defined in alphabetical order:
X    def capitalize(self): return self.__class__(self.data.capitalize())
X    def center(self, width): return self.__class__(self.data.center(width))
X    def count(self, sub, start=0, end=sys.maxint):
X        return self.data.count(sub, start, end)
X    def encode(self, encoding=None, errors=None): # XXX improve this?
X        if encoding:
X            if errors:
X                return self.__class__(self.data.encode(encoding, errors))
X            else:
X                return self.__class__(self.data.encode(encoding))
X        else: 
X            return self.__class__(self.data.encode())
X    def endswith(self, suffix, start=0, end=sys.maxint):
X        return self.data.endswith(suffix, start, end)
X    def expandtabs(self, tabsize=8): 
X        return self.__class__(self.data.expandtabs(tabsize))
X    def find(self, sub, start=0, end=sys.maxint): 
X        return self.data.find(sub, start, end)
X    def index(self, sub, start=0, end=sys.maxint): 
X        return self.data.index(sub, start, end)
X    def isdecimal(self): return self.data.isdecimal()
X    def isdigit(self): return self.data.isdigit()
X    def islower(self): return self.data.islower()
X    def isnumeric(self): return self.data.isnumeric()
X    def isspace(self): return self.data.isspace()
X    def istitle(self): return self.data.istitle()
X    def isupper(self): return self.data.isupper()
X    def join(self, seq): return self.data.join(seq)
X    def ljust(self, width): return self.__class__(self.data.ljust(width))
X    def lower(self): return self.__class__(self.data.lower())
X    def lstrip(self): return self.__class__(self.data.lstrip())
X    def replace(self, old, new, maxsplit=-1): 
X        return self.__class__(self.data.replace(old, new, maxsplit))
X    def rfind(self, sub, start=0, end=sys.maxint): 
X        return self.data.rfind(sub, start, end)
X    def rindex(self, sub, start=0, end=sys.maxint): 
X        return self.data.rindex(sub, start, end)
X    def rjust(self, width): return self.__class__(self.data.rjust(width))
X    def rstrip(self): return self.__class__(self.data.rstrip())
X    def split(self, sep=None, maxsplit=-1): 
X        return self.data.split(sep, maxsplit)
X    def splitlines(self, maxsplit=-1): return self.data.splitlines(maxsplit)
X    def startswith(self, prefix, start=0, end=sys.maxint): 
X        return self.data.startswith(prefix, start, end)
X    def strip(self): return self.__class__(self.data.strip())
X    def swapcase(self): return self.__class__(self.data.swapcase())
X    def title(self): return self.__class__(self.data.title())
X    def translate(self, table, deletechars=""): 
X        return self.__class__(self.data.translate(table, deletechars))
X    def upper(self): return self.__class__(self.data.upper())
X
class MutableString(UserString):
X    """mutable string objects
X
X    Python strings are immutable objects.  This has the advantage, that
X    strings may be used as dictionary keys.  If this property isn't needed
X    and you insist on changing string values in place instead, you may cheat
X    and use MutableString.
X
X    But the purpose of this class is an educational one: to prevent
X    people from inventing their own mutable string class derived
X    from UserString and than forget thereby to remove (override) the
X    __hash__ method inherited from ^UserString.  This would lead to
X    errors that would be very hard to track down.
X
X    A faster and better solution is to rewrite your program using lists."""
X    def __init__(self, string=""):
X        self.data = string
X    def __hash__(self): 
X        raise TypeError, "unhashable type (it is mutable)"
X    def __setitem__(self, index, sub):
X        if index < 0 or index >= len(self.data): raise IndexError
X        self.data = self.data[:index] + sub + self.data[index+1:]
X    def __delitem__(self, index):
X        if index < 0 or index >= len(self.data): raise IndexError
X        self.data = self.data[:index] + self.data[index+1:]
X    def __setslice__(self, start, end, sub):
X        start = max(start, 0); end = max(end, 0)
X        if isinstance(sub, UserString):
X            self.data = self.data[:start]+sub.data+self.data[end:]
X        elif isinstance(sub, StringType) or isinstance(sub, UnicodeType):
X            self.data = self.data[:start]+sub+self.data[end:]
X        else:
X            self.data =  self.data[:start]+str(sub)+self.data[end:]
X    def __delslice__(self, start, end):
X        start = max(start, 0); end = max(end, 0)
X        self.data = self.data[:start] + self.data[end:]
X    def immutable(self):
X        return UserString(self.data)
X    
if __name__ == "__main__":
X    # execute the regression test to stdout, if called as a script:
X    import os
X    called_in_dir, called_as = os.path.split(sys.argv[0])
X    called_in_dir = os.path.abspath(called_in_dir)
X    called_as, py = os.path.splitext(called_as)
X    sys.path.append(os.path.join(called_in_dir, 'test'))
X    if '-q' in sys.argv:
X        import test_support
X        test_support.verbose = 0
X    __import__('test_' + called_as.lower())
SHAR_EOF
  $shar_touch -am 04030006100 'src/Lib/UserString.py' &&
  chmod 0775 'src/Lib/UserString.py' ||
  $echo 'restore of' 'src/Lib/UserString.py' 'failed'
  if ( md5sum --help </dev/null 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version </dev/null 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'src/Lib/UserString.py:' 'MD5 check failed'
16ba5d7ab3cefa6d75d8fe270e05957a  src/Lib/UserString.py
SHAR_EOF
  else
    shar_count="`LC_ALL=C wc -c < 'src/Lib/UserString.py'`"
    test 7077 -eq "$shar_count" ||
    $echo 'src/Lib/UserString.py:' 'original size' '7077,' 'current size' "$shar_count!"
  fi
fi
# ============= src/Lib/test/test_userstring.py ==============
if test ! -d 'src/Lib/test'; then
  $echo $echo_n 'x -' 'src/Lib/test: '$echo_c
  if mkdir 'src/Lib/test'; then $echo 'created'; else $echo 'failed to create'; fi
fi
if test -f 'src/Lib/test/test_userstring.py' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'src/Lib/test/test_userstring.py' '(file already exists)'
else
  $echo 'x -' extracting 'src/Lib/test/test_userstring.py' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/Lib/test/test_userstring.py' &&
#!/usr/bin/env python
import sys, string
from test_support import verbose
# UserString is a wrapper around the native builtin string type.
# UserString instances should behave similar to builtin string objects.
# The test cases were in part derived from 'test_string.py'.
from UserString import UserString
X
if __name__ == "__main__":
X    verbose = 0
X
tested_methods = {}
X
def test(methodname, input, *args):
X    global tested_methods
X    tested_methods[methodname] = 1
X    if verbose:
X        print '%s.%s(%s) ' % (input, methodname, args),
X    u = UserString(input)
X    objects = [input, u, UserString(u)]
X    res = [""] * 3
X    for i in range(3):
X	object = objects[i]
X	try:
X	    f = getattr(object, methodname)
X	    res[i] = apply(f, args)
X	except:
X	    res[i] = sys.exc_type
X    if res[0] != res[1]:
X        if verbose:
X            print 'no'
X        print `input`, f, `res[0]`, "<>", `res[1]`
X    else:
X        if verbose:
X            print 'yes'
X    if res[1] != res[2]:
X        if verbose:
X            print 'no'
X        print `input`, f, `res[1]`, "<>", `res[2]`
X    else:
X        if verbose:
X            print 'yes'
X
test('capitalize', ' hello ')
test('capitalize', 'hello ')
X
test('center', 'foo', 0)
test('center', 'foo', 3)
test('center', 'foo', 16)
X
test('ljust', 'foo', 0)
test('ljust', 'foo', 3)
test('ljust', 'foo', 16)
X
test('rjust', 'foo', 0)
test('rjust', 'foo', 3)
test('rjust', 'foo', 16)
X
test('count', 'abcabcabc', 'abc')
test('count', 'abcabcabc', 'abc', 1)
test('count', 'abcabcabc', 'abc', -1)
test('count', 'abcabcabc', 'abc', 7)
test('count', 'abcabcabc', 'abc', 0, 3)
test('count', 'abcabcabc', 'abc', 0, 333)
X
test('find', 'abcdefghiabc', 'abc')
test('find', 'abcdefghiabc', 'abc', 1)
test('find', 'abcdefghiabc', 'def', 4)
test('rfind', 'abcdefghiabc', 'abc')
X
test('index', 'abcabcabc', 'abc')
test('index', 'abcabcabc', 'abc', 1)
test('index', 'abcabcabc', 'abc', -1)
test('index', 'abcabcabc', 'abc', 7)
test('index', 'abcabcabc', 'abc', 0, 3)
test('index', 'abcabcabc', 'abc', 0, 333)
X
test('rindex', 'abcabcabc', 'abc')
test('rindex', 'abcabcabc', 'abc', 1)
test('rindex', 'abcabcabc', 'abc', -1)
test('rindex', 'abcabcabc', 'abc', 7)
test('rindex', 'abcabcabc', 'abc', 0, 3)
test('rindex', 'abcabcabc', 'abc', 0, 333)
X
X
test('lower', 'HeLLo')
test('lower', 'hello')
test('upper', 'HeLLo')
test('upper', 'HELLO')
X
test('title', ' hello ')
test('title', 'hello ')
test('title', "fOrMaT thIs aS titLe String")
test('title', "fOrMaT,thIs-aS*titLe;String")
test('title', "getInt")
X
test('expandtabs', 'abc\rab\tdef\ng\thi')
test('expandtabs', 'abc\rab\tdef\ng\thi', 8)
test('expandtabs', 'abc\rab\tdef\ng\thi', 4)
test('expandtabs', 'abc\r\nab\tdef\ng\thi', 4)
X
test('islower', 'a')
test('islower', 'A')
test('islower', '\n')
test('islower', 'abc')
test('islower', 'aBc')
test('islower', 'abc\n')
X
test('isupper', 'a')
test('isupper', 'A')
test('isupper', '\n')
test('isupper', 'ABC')
test('isupper', 'AbC')
test('isupper', 'ABC\n')
X
test('isdigit', '  0123456789')
test('isdigit', '56789')
test('isdigit', '567.89')
test('isdigit', '0123456789abc')
X
test('isspace', '')
test('isspace', ' ')
test('isspace', ' \t')
test('isspace', ' \t\f\n')
X
test('istitle', 'a')
test('istitle', 'A')
test('istitle', '\n')
test('istitle', 'A Titlecased Line')
test('istitle', 'A\nTitlecased Line')
test('istitle', 'A Titlecased, Line')
test('istitle', 'Not a capitalized String')
test('istitle', 'Not\ta Titlecase String')
test('istitle', 'Not--a Titlecase String')
X
test('splitlines', "abc\ndef\n\rghi")
test('splitlines', "abc\ndef\n\r\nghi")
test('splitlines', "abc\ndef\r\nghi")
test('splitlines', "abc\ndef\r\nghi\n")
test('splitlines', "abc\ndef\r\nghi\n\r")
test('splitlines', "\nabc\ndef\r\nghi\n\r")
test('splitlines', "\nabc\ndef\r\nghi\n\r")
test('splitlines', "\nabc\ndef\r\nghi\n\r")
X
test('split', 'this is the split function')
test('split', 'a|b|c|d', '|')
test('split', 'a|b|c|d', '|', 2)
test('split', 'a b c d', None, 1)
test('split', 'a b c d', None, 2)
test('split', 'a b c d', None, 3)
test('split', 'a b c d', None, 4)
test('split', 'a b c d', None, 0)
test('split', 'a  b  c  d', None, 2)
test('split', 'a b c d ')
X
# join now works with any sequence type
class Sequence:
X    def __init__(self): self.seq = 'wxyz'
X    def __len__(self): return len(self.seq)
X    def __getitem__(self, i): return self.seq[i]
X
test('join', '', ('a', 'b', 'c', 'd'))
test('join', '', Sequence())
test('join', '', 7)
X
class BadSeq(Sequence):
X    def __init__(self): self.seq = [7, 'hello', 123L]
X
test('join', '', BadSeq())
X
test('strip', '   hello   ')
test('lstrip', '   hello   ')
test('rstrip', '   hello   ')
test('strip', 'hello')
X
test('swapcase', 'HeLLo cOmpUteRs')
transtable = string.maketrans("abc", "xyz")
test('translate', 'xyzabcdef', transtable, 'def')
X
transtable = string.maketrans('a', 'A')
test('translate', 'abc', transtable)
test('translate', 'xyz', transtable)
X
test('replace', 'one!two!three!', '!', '@', 1)
test('replace', 'one!two!three!', '!', '')
test('replace', 'one!two!three!', '!', '@', 2)
test('replace', 'one!two!three!', '!', '@', 3)
test('replace', 'one!two!three!', '!', '@', 4)
test('replace', 'one!two!three!', '!', '@', 0)
test('replace', 'one!two!three!', '!', '@')
test('replace', 'one!two!three!', 'x', '@')
test('replace', 'one!two!three!', 'x', '@', 2)
X
test('startswith', 'hello', 'he')
test('startswith', 'hello', 'hello')
test('startswith', 'hello', 'hello world')
test('startswith', 'hello', '')
test('startswith', 'hello', 'ello')
test('startswith', 'hello', 'ello', 1)
test('startswith', 'hello', 'o', 4)
test('startswith', 'hello', 'o', 5)
test('startswith', 'hello', '', 5)
test('startswith', 'hello', 'lo', 6)
test('startswith', 'helloworld', 'lowo', 3)
test('startswith', 'helloworld', 'lowo', 3, 7)
test('startswith', 'helloworld', 'lowo', 3, 6)
X
test('endswith', 'hello', 'lo')
test('endswith', 'hello', 'he')
test('endswith', 'hello', '')
test('endswith', 'hello', 'hello world')
test('endswith', 'helloworld', 'worl')
test('endswith', 'helloworld', 'worl', 3, 9)
test('endswith', 'helloworld', 'world', 3, 12)
test('endswith', 'helloworld', 'lowo', 1, 7)
test('endswith', 'helloworld', 'lowo', 2, 7)
test('endswith', 'helloworld', 'lowo', 3, 7)
test('endswith', 'helloworld', 'lowo', 4, 7)
test('endswith', 'helloworld', 'lowo', 3, 8)
test('endswith', 'ab', 'ab', 0, 1)
test('endswith', 'ab', 'ab', 0, 0)
X
# TODO: test cases for: int, long, float, complex, +, * and cmp
s = ""
for builtin_method in dir(s):
X    if not tested_methods.has_key(builtin_method):
X	print "no regression test case for method '"+builtin_method+"'"
X
SHAR_EOF
  $shar_touch -am 04030025100 'src/Lib/test/test_userstring.py' &&
  chmod 0775 'src/Lib/test/test_userstring.py' ||
  $echo 'restore of' 'src/Lib/test/test_userstring.py' 'failed'
  if ( md5sum --help </dev/null 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version </dev/null 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'src/Lib/test/test_userstring.py:' 'MD5 check failed'
bbbdf7e85913aa80e38e2469991b3cac  src/Lib/test/test_userstring.py
SHAR_EOF
  else
    shar_count="`LC_ALL=C wc -c < 'src/Lib/test/test_userstring.py'`"
    test 6599 -eq "$shar_count" ||
    $echo 'src/Lib/test/test_userstring.py:' 'original size' '6599,' 'current size' "$shar_count!"
  fi
fi
# ============= src/Lib/test/output/test_userstring ==============
if test ! -d 'src/Lib/test/output'; then
  $echo $echo_n 'x -' 'src/Lib/test/output: '$echo_c
  if mkdir 'src/Lib/test/output'; then $echo 'created'; else $echo 'failed to create'; fi
fi
if test -f 'src/Lib/test/output/test_userstring' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'src/Lib/test/output/test_userstring' '(file already exists)'
else
  $echo 'x -' extracting 'src/Lib/test/output/test_userstring' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/Lib/test/output/test_userstring' &&
test_userstring
SHAR_EOF
  $shar_touch -am 04030030100 'src/Lib/test/output/test_userstring' &&
  chmod 0660 'src/Lib/test/output/test_userstring' ||
  $echo 'restore of' 'src/Lib/test/output/test_userstring' 'failed'
  if ( md5sum --help </dev/null 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version </dev/null 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'src/Lib/test/output/test_userstring:' 'MD5 check failed'
8a16c32581de42c338366cb9f7488e4c  src/Lib/test/output/test_userstring
SHAR_EOF
  else
    shar_count="`LC_ALL=C wc -c < 'src/Lib/test/output/test_userstring'`"
    test 16 -eq "$shar_count" ||
    $echo 'src/Lib/test/output/test_userstring:' 'original size' '16,' 'current size' "$shar_count!"
  fi
fi
$echo $shar_n 'x -' 'lock directory' "\`_sh29194': " $shar_c
if rm -fr _sh29194; then
  $echo 'removed'
else
  $echo 'failed to remove'
fi
exit 0