diff options
-rw-r--r-- | Lib/dos-8x3/cookie.py | 726 | ||||
-rw-r--r-- | Lib/dos-8x3/exceptio.py | 247 | ||||
-rw-r--r-- | Lib/dos-8x3/string_t.py | 202 | ||||
-rw-r--r-- | Lib/dos-8x3/test_aug.py | 232 | ||||
-rw-r--r-- | Lib/dos-8x3/test_cla.py | 219 | ||||
-rw-r--r-- | Lib/dos-8x3/test_com.py | 16 | ||||
-rw-r--r-- | Lib/dos-8x3/test_coo.py | 40 | ||||
-rw-r--r-- | Lib/dos-8x3/test_dos.py | 49 | ||||
-rw-r--r-- | Lib/dos-8x3/test_fil.py | 45 | ||||
-rw-r--r-- | Lib/dos-8x3/test_get.py | 101 | ||||
-rw-r--r-- | Lib/dos-8x3/test_lar.py | 129 | ||||
-rw-r--r-- | Lib/dos-8x3/test_min.py | 331 | ||||
-rw-r--r-- | Lib/dos-8x3/test_par.py | 178 | ||||
-rw-r--r-- | Lib/dos-8x3/test_pol.py | 172 | ||||
-rw-r--r-- | Lib/dos-8x3/test_pos.py | 42 | ||||
-rw-r--r-- | Lib/dos-8x3/test_url.py | 0 | ||||
-rw-r--r-- | Lib/dos-8x3/threadst.py | 9 | ||||
-rw-r--r-- | Lib/dos-8x3/webbrows.py | 229 |
18 files changed, 2711 insertions, 256 deletions
diff --git a/Lib/dos-8x3/cookie.py b/Lib/dos-8x3/cookie.py new file mode 100644 index 0000000..67259af --- /dev/null +++ b/Lib/dos-8x3/cookie.py @@ -0,0 +1,726 @@ +#!/usr/bin/env python +# + +#### +# Copyright 2000 by Timothy O'Malley <timo@alum.mit.edu> +# +# All Rights Reserved +# +# Permission to use, copy, modify, and distribute this software +# and its documentation for any purpose and without fee is hereby +# granted, provided that the above copyright notice appear in all +# copies and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Timothy O'Malley not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# Timothy O'Malley DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS, IN NO EVENT SHALL Timothy O'Malley BE LIABLE FOR +# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# +#### +# +# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp +# by Timothy O'Malley <timo@alum.mit.edu> +# +# Cookie.py is a Python module for the handling of HTTP +# cookies as a Python dictionary. See RFC 2109 for more +# information on cookies. +# +# The original idea to treat Cookies as a dictionary came from +# Dave Mitchell (davem@magnet.com) in 1995, when he released the +# first version of nscookie.py. +# +#### + +""" +Here's a sample session to show how to use this module. +At the moment, this is the only documentation. + +The Basics +---------- + +Importing is easy.. + + >>> import Cookie + +Most of the time you start by creating a cookie. Cookies come in +three flavors, each with slighly different encoding semanitcs, but +more on that later. + + >>> C = Cookie.SimpleCookie() + >>> C = Cookie.SerialCookie() + >>> C = Cookie.SmartCookie() + +[Note: Long-time users of Cookie.py will remember using +Cookie.Cookie() to create an Cookie object. Although deprecated, it +is still supported by the code. See the Backward Compatibility notes +for more information.] + +Once you've created your Cookie, you can add values just as if it were +a dictionary. + + >>> C = Cookie.SmartCookie() + >>> C["fig"] = "newton" + >>> C["sugar"] = "wafer" + >>> print C + Set-Cookie: sugar=wafer; + Set-Cookie: fig=newton; + +Notice that the printable representation of a Cookie is the +appropriate format for a Set-Cookie: header. This is the +default behavior. You can change the header and printed +attributes by using the the .output() function + + >>> C = Cookie.SmartCookie() + >>> C["rocky"] = "road" + >>> C["rocky"]["path"] = "/cookie" + >>> print C.output(header="Cookie:") + Cookie: rocky=road; Path=/cookie; + >>> print C.output(attrs=[], header="Cookie:") + Cookie: rocky=road; + +The load() method of a Cookie extracts cookies from a string. In a +CGI script, you would use this method to extract the cookies from the +HTTP_COOKIE environment variable. + + >>> C = Cookie.SmartCookie() + >>> C.load("chips=ahoy; vienna=finger") + >>> print C + Set-Cookie: vienna=finger; + Set-Cookie: chips=ahoy; + +The load() method is darn-tootin smart about identifying cookies +within a string. Escaped quotation marks, nested semicolons, and other +such trickeries do not confuse it. + + >>> C = Cookie.SmartCookie() + >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";') + >>> print C + Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"; + +Each element of the Cookie also supports all of the RFC 2109 +Cookie attributes. Here's an example which sets the Path +attribute. + + >>> C = Cookie.SmartCookie() + >>> C["oreo"] = "doublestuff" + >>> C["oreo"]["path"] = "/" + >>> print C + Set-Cookie: oreo="doublestuff"; Path=/; + +Each dictionary element has a 'value' attribute, which gives you +back the value associated with the key. + + >>> C = Cookie.SmartCookie() + >>> C["twix"] = "none for you" + >>> C["twix"].value + 'none for you' + + +A Bit More Advanced +------------------- + +As mentioned before, there are three different flavors of Cookie +objects, each with different encoding/decoding semantics. This +section briefly discusses the differences. + +SimpleCookie + +The SimpleCookie expects that all values should be standard strings. +Just to be sure, SimpleCookie invokes the str() builtin to convert +the value to a string, when the values are set dictionary-style. + + >>> C = Cookie.SimpleCookie() + >>> C["number"] = 7 + >>> C["string"] = "seven" + >>> C["number"].value + '7' + >>> C["string"].value + 'seven' + >>> print C + Set-Cookie: number=7; + Set-Cookie: string=seven; + + +SerialCookie + +The SerialCookie expects that all values should be serialized using +cPickle (or pickle, if cPickle isn't available). As a result of +serializing, SerialCookie can save almost any Python object to a +value, and recover the exact same object when the cookie has been +returned. (SerialCookie can yield some strange-looking cookie +values, however.) + + >>> C = Cookie.SerialCookie() + >>> C["number"] = 7 + >>> C["string"] = "seven" + >>> C["number"].value + 7 + >>> C["string"].value + 'seven' + >>> print C + Set-Cookie: number="I7\012."; + Set-Cookie: string="S'seven'\012p1\012."; + +Be warned, however, if SerialCookie cannot de-serialize a value (because +it isn't a valid pickle'd object), IT WILL RAISE AN EXCEPTION. + + +SmartCookie + +The SmartCookie combines aspects of each of the other two flavors. +When setting a value in a dictionary-fashion, the SmartCookie will +serialize (ala cPickle) the value *if and only if* it isn't a +Python string. String objects are *not* serialized. Similarly, +when the load() method parses out values, it attempts to de-serialize +the value. If it fails, then it fallsback to treating the value +as a string. + + >>> C = Cookie.SmartCookie() + >>> C["number"] = 7 + >>> C["string"] = "seven" + >>> C["number"].value + 7 + >>> C["string"].value + 'seven' + >>> print C + Set-Cookie: number="I7\012."; + Set-Cookie: string=seven; + + +Backwards Compatibility +----------------------- + +In order to keep compatibilty with earlier versions of Cookie.py, +it is still possible to use Cookie.Cookie() to create a Cookie. In +fact, this simply returns a SmartCookie. + + >>> C = Cookie.Cookie() + >>> C.__class__ + <class Cookie.SmartCookie at 99f88> + + +Finis. +""" #" +# ^ +# |----helps out font-lock + +# +# Import our required modules +# +import string, sys +from UserDict import UserDict + +try: + from cPickle import dumps, loads +except ImportError: + from pickle import dumps, loads + +try: + import re +except ImportError: + raise ImportError, "Cookie.py requires 're' from Python 1.5 or later" + + +# +# Define an exception visible to External modules +# +class CookieError(Exception): + pass + + +# These quoting routines conform to the RFC2109 specification, which in +# turn references the character definitions from RFC2068. They provide +# a two-way quoting algorithm. Any non-text character is translated +# into a 4 character sequence: a forward-slash followed by the +# three-digit octal equivalent of the character. Any '\' or '"' is +# quoted with a preceeding '\' slash. +# +# These are taken from RFC2068 and RFC2109. +# _LegalChars is the list of chars which don't require "'s +# _Translator hash-table for fast quoting +# +_LegalChars = string.letters + string.digits + "!#$%&'*+-.^_`|~" +_Translator = { + '\000' : '\\000', '\001' : '\\001', '\002' : '\\002', + '\003' : '\\003', '\004' : '\\004', '\005' : '\\005', + '\006' : '\\006', '\007' : '\\007', '\010' : '\\010', + '\011' : '\\011', '\012' : '\\012', '\013' : '\\013', + '\014' : '\\014', '\015' : '\\015', '\016' : '\\016', + '\017' : '\\017', '\020' : '\\020', '\021' : '\\021', + '\022' : '\\022', '\023' : '\\023', '\024' : '\\024', + '\025' : '\\025', '\026' : '\\026', '\027' : '\\027', + '\030' : '\\030', '\031' : '\\031', '\032' : '\\032', + '\033' : '\\033', '\034' : '\\034', '\035' : '\\035', + '\036' : '\\036', '\037' : '\\037', + + '"' : '\\"', '\\' : '\\\\', + + '\177' : '\\177', '\200' : '\\200', '\201' : '\\201', + '\202' : '\\202', '\203' : '\\203', '\204' : '\\204', + '\205' : '\\205', '\206' : '\\206', '\207' : '\\207', + '\210' : '\\210', '\211' : '\\211', '\212' : '\\212', + '\213' : '\\213', '\214' : '\\214', '\215' : '\\215', + '\216' : '\\216', '\217' : '\\217', '\220' : '\\220', + '\221' : '\\221', '\222' : '\\222', '\223' : '\\223', + '\224' : '\\224', '\225' : '\\225', '\226' : '\\226', + '\227' : '\\227', '\230' : '\\230', '\231' : '\\231', + '\232' : '\\232', '\233' : '\\233', '\234' : '\\234', + '\235' : '\\235', '\236' : '\\236', '\237' : '\\237', + '\240' : '\\240', '\241' : '\\241', '\242' : '\\242', + '\243' : '\\243', '\244' : '\\244', '\245' : '\\245', + '\246' : '\\246', '\247' : '\\247', '\250' : '\\250', + '\251' : '\\251', '\252' : '\\252', '\253' : '\\253', + '\254' : '\\254', '\255' : '\\255', '\256' : '\\256', + '\257' : '\\257', '\260' : '\\260', '\261' : '\\261', + '\262' : '\\262', '\263' : '\\263', '\264' : '\\264', + '\265' : '\\265', '\266' : '\\266', '\267' : '\\267', + '\270' : '\\270', '\271' : '\\271', '\272' : '\\272', + '\273' : '\\273', '\274' : '\\274', '\275' : '\\275', + '\276' : '\\276', '\277' : '\\277', '\300' : '\\300', + '\301' : '\\301', '\302' : '\\302', '\303' : '\\303', + '\304' : '\\304', '\305' : '\\305', '\306' : '\\306', + '\307' : '\\307', '\310' : '\\310', '\311' : '\\311', + '\312' : '\\312', '\313' : '\\313', '\314' : '\\314', + '\315' : '\\315', '\316' : '\\316', '\317' : '\\317', + '\320' : '\\320', '\321' : '\\321', '\322' : '\\322', + '\323' : '\\323', '\324' : '\\324', '\325' : '\\325', + '\326' : '\\326', '\327' : '\\327', '\330' : '\\330', + '\331' : '\\331', '\332' : '\\332', '\333' : '\\333', + '\334' : '\\334', '\335' : '\\335', '\336' : '\\336', + '\337' : '\\337', '\340' : '\\340', '\341' : '\\341', + '\342' : '\\342', '\343' : '\\343', '\344' : '\\344', + '\345' : '\\345', '\346' : '\\346', '\347' : '\\347', + '\350' : '\\350', '\351' : '\\351', '\352' : '\\352', + '\353' : '\\353', '\354' : '\\354', '\355' : '\\355', + '\356' : '\\356', '\357' : '\\357', '\360' : '\\360', + '\361' : '\\361', '\362' : '\\362', '\363' : '\\363', + '\364' : '\\364', '\365' : '\\365', '\366' : '\\366', + '\367' : '\\367', '\370' : '\\370', '\371' : '\\371', + '\372' : '\\372', '\373' : '\\373', '\374' : '\\374', + '\375' : '\\375', '\376' : '\\376', '\377' : '\\377' + } + +def _quote(str, LegalChars=_LegalChars, + join=string.join, idmap=string._idmap, translate=string.translate): + # + # If the string does not need to be double-quoted, + # then just return the string. Otherwise, surround + # the string in doublequotes and precede quote (with a \) + # special characters. + # + if "" == translate(str, idmap, LegalChars): + return str + else: + return '"' + join( map(_Translator.get, str, str), "" ) + '"' +# end _quote + + +_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]") +_QuotePatt = re.compile(r"[\\].") + +def _unquote(str, join=string.join, atoi=string.atoi): + # If there aren't any doublequotes, + # then there can't be any special characters. See RFC 2109. + if len(str) < 2: + return str + if str[0] != '"' or str[-1] != '"': + return str + + # We have to assume that we must decode this string. + # Down to work. + + # Remove the "s + str = str[1:-1] + + # Check for special sequences. Examples: + # \012 --> \n + # \" --> " + # + i = 0 + n = len(str) + res = [] + while 0 <= i < n: + Omatch = _OctalPatt.search(str, i) + Qmatch = _QuotePatt.search(str, i) + if not Omatch and not Qmatch: # Neither matched + res.append(str[i:]) + break + # else: + j = k = -1 + if Omatch: j = Omatch.start(0) + if Qmatch: k = Qmatch.start(0) + if Qmatch and ( not Omatch or k < j ): # QuotePatt matched + res.append(str[i:k]) + res.append(str[k+1]) + i = k+2 + else: # OctalPatt matched + res.append(str[i:j]) + res.append( chr( atoi(str[j+1:j+4], 8) ) ) + i = j+4 + return join(res, "") +# end _unquote + +# The _getdate() routine is used to set the expiration time in +# the cookie's HTTP header. By default, _getdate() returns the +# current time in the appropriate "expires" format for a +# Set-Cookie header. The one optional argument is an offset from +# now, in seconds. For example, an offset of -3600 means "one hour ago". +# The offset may be a floating point number. +# + +_weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + +_monthname = [None, + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + +def _getdate(future=0, weekdayname=_weekdayname, monthname=_monthname): + from time import gmtime, time + now = time() + year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future) + return "%s, %02d-%3s-%4d %02d:%02d:%02d GMT" % \ + (weekdayname[wd], day, monthname[month], year, hh, mm, ss) + + +# +# A class to hold ONE key,value pair. +# In a cookie, each such pair may have several attributes. +# so this class is used to keep the attributes associated +# with the appropriate key,value pair. +# This class also includes a coded_value attribute, which +# is used to hold the network representation of the +# value. This is most useful when Python objects are +# pickled for network transit. +# + +class Morsel(UserDict): + # RFC 2109 lists these attributes as reserved: + # path comment domain + # max-age secure version + # + # For historical reasons, these attributes are also reserved: + # expires + # + # This dictionary provides a mapping from the lowercase + # variant on the left to the appropriate traditional + # formatting on the right. + _reserved = { "expires" : "expires", + "path" : "Path", + "comment" : "Comment", + "domain" : "Domain", + "max-age" : "Max-Age", + "secure" : "secure", + "version" : "Version", + } + _reserved_keys = _reserved.keys() + + def __init__(self): + # Set defaults + self.key = self.value = self.coded_value = None + UserDict.__init__(self) + + # Set default attributes + for K in self._reserved_keys: + UserDict.__setitem__(self, K, "") + # end __init__ + + def __setitem__(self, K, V): + K = string.lower(K) + if not K in self._reserved_keys: + raise CookieError("Invalid Attribute %s" % K) + UserDict.__setitem__(self, K, V) + # end __setitem__ + + def isReservedKey(self, K): + return string.lower(K) in self._reserved_keys + # end isReservedKey + + def set(self, key, val, coded_val, + LegalChars=_LegalChars, + idmap=string._idmap, translate=string.translate ): + # First we verify that the key isn't a reserved word + # Second we make sure it only contains legal characters + if string.lower(key) in self._reserved_keys: + raise CookieError("Attempt to set a reserved key: %s" % key) + if "" != translate(key, idmap, LegalChars): + raise CookieError("Illegal key value: %s" % key) + + # It's a good key, so save it. + self.key = key + self.value = val + self.coded_value = coded_val + # end set + + def output(self, attrs=None, header = "Set-Cookie:"): + return "%s %s" % ( header, self.OutputString(attrs) ) + + __str__ = output + + def __repr__(self): + return '<%s: %s=%s>' % (self.__class__.__name__, + self.key, repr(self.value) ) + + def js_output(self, attrs=None): + # Print javascript + return """ + <SCRIPT LANGUAGE="JavaScript"> + <!-- begin hiding + document.cookie = \"%s\" + // end hiding --> + </script> + """ % ( self.OutputString(attrs), ) + # end js_output() + + def OutputString(self, attrs=None): + # Build up our result + # + result = [] + RA = result.append + + # First, the key=value pair + RA("%s=%s;" % (self.key, self.coded_value)) + + # Now add any defined attributes + if attrs == None: + attrs = self._reserved_keys + for K,V in self.items(): + if V == "": continue + if K not in attrs: continue + if K == "expires" and type(V) == type(1): + RA("%s=%s;" % (self._reserved[K], _getdate(V))) + elif K == "max-age" and type(V) == type(1): + RA("%s=%d;" % (self._reserved[K], V)) + elif K == "secure": + RA("%s;" % self._reserved[K]) + else: + RA("%s=%s;" % (self._reserved[K], V)) + + # Return the result + return string.join(result, " ") + # end OutputString +# end Morsel class + + + +# +# Pattern for finding cookie +# +# This used to be strict parsing based on the RFC2109 and RFC2068 +# specifications. I have since discovered that MSIE 3.0x doesn't +# follow the character rules outlined in those specs. As a +# result, the parsing rules here are less strict. +# + +_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{]" +_CookiePattern = re.compile( + r"(?x)" # This is a Verbose pattern + r"(?P<key>" # Start of group 'key' + ""+ _LegalCharsPatt +"+" # Any word of at least one letter + r")" # End of group 'key' + r"\s*=\s*" # Equal Sign + r"(?P<val>" # Start of group 'val' + r'"(?:[^\\"]|\\.)*"' # Any doublequoted string + r"|" # or + ""+ _LegalCharsPatt +"*" # Any word or empty string + r")" # End of group 'val' + r"\s*;?" # Probably ending in a semi-colon + ) + + +# At long last, here is the cookie class. +# Using this class is almost just like using a dictionary. +# See this module's docstring for example usage. +# +class BaseCookie(UserDict): + # A container class for a set of Morsels + # + + def value_decode(self, val): + """real_value, coded_value = value_decode(STRING) + Called prior to setting a cookie's value from the network + representation. The VALUE is the value read from HTTP + header. + Override this function to modify the behavior of cookies. + """ + return val, val + # end value_encode + + def value_encode(self, val): + """real_value, coded_value = value_encode(VALUE) + Called prior to setting a cookie's value from the dictionary + representation. The VALUE is the value being assigned. + Override this function to modify the behavior of cookies. + """ + strval = str(val) + return strval, strval + # end value_encode + + def __init__(self, input=None): + UserDict.__init__(self) + if input: self.load(input) + # end __init__ + + def __set(self, key, real_value, coded_value): + """Private method for setting a cookie's value""" + M = self.get(key, Morsel()) + M.set(key, real_value, coded_value) + UserDict.__setitem__(self, key, M) + # end __set + + def __setitem__(self, key, value): + """Dictionary style assignment.""" + rval, cval = self.value_encode(value) + self.__set(key, rval, cval) + # end __setitem__ + + def output(self, attrs=None, header="Set-Cookie:", sep="\n"): + """Return a string suitable for HTTP.""" + result = [] + for K,V in self.items(): + result.append( V.output(attrs, header) ) + return string.join(result, sep) + # end output + + __str__ = output + + def __repr__(self): + L = [] + for K,V in self.items(): + L.append( '%s=%s' % (K,repr(V.value) ) ) + return '<%s: %s>' % (self.__class__.__name__, string.join(L)) + + def js_output(self, attrs=None): + """Return a string suitable for JavaScript.""" + result = [] + for K,V in self.items(): + result.append( V.js_output(attrs) ) + return string.join(result, "") + # end js_output + + def load(self, rawdata): + """Load cookies from a string (presumably HTTP_COOKIE) or + from a dictionary. Loading cookies from a dictionary 'd' + is equivalent to calling: + map(Cookie.__setitem__, d.keys(), d.values()) + """ + if type(rawdata) == type(""): + self.__ParseString(rawdata) + else: + self.update(rawdata) + return + # end load() + + def __ParseString(self, str, patt=_CookiePattern): + i = 0 # Our starting point + n = len(str) # Length of string + M = None # current morsel + + while 0 <= i < n: + # Start looking for a cookie + match = patt.search(str, i) + if not match: break # No more cookies + + K,V = match.group("key"), match.group("val") + i = match.end(0) + + # Parse the key, value in case it's metainfo + if K[0] == "$": + # We ignore attributes which pertain to the cookie + # mechanism as a whole. See RFC 2109. + # (Does anyone care?) + if M: + M[ K[1:] ] = V + elif string.lower(K) in Morsel._reserved_keys: + if M: + M[ K ] = _unquote(V) + else: + rval, cval = self.value_decode(V) + self.__set(K, rval, cval) + M = self[K] + # end __ParseString +# end BaseCookie class + +class SimpleCookie(BaseCookie): + """SimpleCookie + SimpleCookie supports strings as cookie values. When setting + the value using the dictionary assignment notation, SimpleCookie + calls the builtin str() to convert the value to a string. Values + received from HTTP are kept as strings. + """ + def value_decode(self, val): + return _unquote( val ), val + def value_encode(self, val): + strval = str(val) + return strval, _quote( strval ) +# end SimpleCookie + +class SerialCookie(BaseCookie): + """SerialCookie + SerialCookie supports arbitrary objects as cookie values. All + values are serialized (using cPickle) before being sent to the + client. All incoming values are assumed to be valid Pickle + representations. IF AN INCOMING VALUE IS NOT IN A VALID PICKLE + FORMAT, THEN AN EXCEPTION WILL BE RAISED. + + Note: Large cookie values add overhead because they must be + retransmitted on every HTTP transaction. + + Note: HTTP has a 2k limit on the size of a cookie. This class + does not check for this limit, so be careful!!! + """ + def value_decode(self, val): + # This could raise an exception! + return loads( _unquote(val) ), val + def value_encode(self, val): + return val, _quote( dumps(val) ) +# end SerialCookie + +class SmartCookie(BaseCookie): + """SmartCookie + SmartCookie supports arbitrary objects as cookie values. If the + object is a string, then it is quoted. If the object is not a + string, however, then SmartCookie will use cPickle to serialize + the object into a string representation. + + Note: Large cookie values add overhead because they must be + retransmitted on every HTTP transaction. + + Note: HTTP has a 2k limit on the size of a cookie. This class + does not check for this limit, so be careful!!! + """ + def value_decode(self, val): + strval = _unquote(val) + try: + return loads(strval), val + except: + return strval, val + def value_encode(self, val): + if type(val) == type(""): + return val, _quote(val) + else: + return val, _quote( dumps(val) ) +# end SmartCookie + + +########################################################### +# Backwards Compatibility: Don't break any existing code! + +# We provide Cookie() as an alias for SmartCookie() +Cookie = SmartCookie + +# +########################################################### + + + +#Local Variables: +#tab-width: 4 +#end: diff --git a/Lib/dos-8x3/exceptio.py b/Lib/dos-8x3/exceptio.py deleted file mode 100644 index 43d1c2d..0000000 --- a/Lib/dos-8x3/exceptio.py +++ /dev/null @@ -1,247 +0,0 @@ -"""Class based built-in exception hierarchy. - -New with Python 1.5, all standard built-in exceptions are now class objects by -default. This gives Python's exception handling mechanism a more -object-oriented feel. Traditionally they were string objects. Python will -fallback to string based exceptions if the interpreter is invoked with the -X -option, or if some failure occurs during class exception initialization (in -this case a warning will be printed). - -Most existing code should continue to work with class based exceptions. Some -tricky uses of IOError may break, but the most common uses should work. - -Here is a rundown of the class hierarchy. You can change this by editing this -file, but it isn't recommended because the old string based exceptions won't -be kept in sync. The class names described here are expected to be found by -the bltinmodule.c file. If you add classes here, you must modify -bltinmodule.c or the exceptions won't be available in the __builtin__ module, -nor will they be accessible from C. - -The classes with a `*' are new since Python 1.5. They are defined as tuples -containing the derived exceptions when string-based exceptions are used. If -you define your own class based exceptions, they should be derived from -Exception. - -Exception(*) - | - +-- SystemExit - +-- StandardError(*) - | - +-- KeyboardInterrupt - +-- ImportError - +-- EnvironmentError(*) - | | - | +-- IOError - | +-- OSError(*) - | | - | +-- WindowsError(*) - | - +-- EOFError - +-- RuntimeError - | | - | +-- NotImplementedError(*) - | - +-- NameError - | | - | +-- UnboundLocalError(*) - | - +-- AttributeError - +-- SyntaxError - +-- TypeError - +-- AssertionError - +-- LookupError(*) - | | - | +-- IndexError - | +-- KeyError - | - +-- ArithmeticError(*) - | | - | +-- OverflowError - | +-- ZeroDivisionError - | +-- FloatingPointError - | - +-- ValueError - | | - | +-- UnicodeError(*) - | - +-- SystemError - +-- MemoryError -""" - -class Exception: - """Proposed base class for all exceptions.""" - def __init__(self, *args): - self.args = args - - def __str__(self): - if not self.args: - return '' - elif len(self.args) == 1: - return str(self.args[0]) - else: - return str(self.args) - - def __getitem__(self, i): - return self.args[i] - -class StandardError(Exception): - """Base class for all standard Python exceptions.""" - pass - -class SyntaxError(StandardError): - """Invalid syntax.""" - filename = lineno = offset = text = None - msg = "" - def __init__(self, *args): - self.args = args - if len(self.args) >= 1: - self.msg = self.args[0] - if len(self.args) == 2: - info = self.args[1] - try: - self.filename, self.lineno, self.offset, self.text = info - except: - pass - def __str__(self): - return str(self.msg) - -class EnvironmentError(StandardError): - """Base class for I/O related errors.""" - def __init__(self, *args): - self.args = args - self.errno = None - self.strerror = None - self.filename = None - if len(args) == 3: - # open() errors give third argument which is the filename. BUT, - # so common in-place unpacking doesn't break, e.g.: - # - # except IOError, (errno, strerror): - # - # we hack args so that it only contains two items. This also - # means we need our own __str__() which prints out the filename - # when it was supplied. - self.errno, self.strerror, self.filename = args - self.args = args[0:2] - if len(args) == 2: - # common case: PyErr_SetFromErrno() - self.errno, self.strerror = args - - def __str__(self): - if self.filename is not None: - return '[Errno %s] %s: %s' % (self.errno, self.strerror, - repr(self.filename)) - elif self.errno and self.strerror: - return '[Errno %s] %s' % (self.errno, self.strerror) - else: - return StandardError.__str__(self) - -class IOError(EnvironmentError): - """I/O operation failed.""" - pass - -class OSError(EnvironmentError): - """OS system call failed.""" - pass - -class WindowsError(OSError): - """MS-Windows OS system call failed.""" - pass - -class RuntimeError(StandardError): - """Unspecified run-time error.""" - pass - -class NotImplementedError(RuntimeError): - """Method or function hasn't been implemented yet.""" - pass - -class SystemError(StandardError): - """Internal error in the Python interpreter. - - Please report this to the Python maintainer, along with the traceback, - the Python version, and the hardware/OS platform and version.""" - pass - -class EOFError(StandardError): - """Read beyond end of file.""" - pass - -class ImportError(StandardError): - """Import can't find module, or can't find name in module.""" - pass - -class TypeError(StandardError): - """Inappropriate argument type.""" - pass - -class ValueError(StandardError): - """Inappropriate argument value (of correct type).""" - pass - -class KeyboardInterrupt(StandardError): - """Program interrupted by user.""" - pass - -class AssertionError(StandardError): - """Assertion failed.""" - pass - -class ArithmeticError(StandardError): - """Base class for arithmetic errors.""" - pass - -class OverflowError(ArithmeticError): - """Result too large to be represented.""" - pass - -class FloatingPointError(ArithmeticError): - """Floating point operation failed.""" - pass - -class ZeroDivisionError(ArithmeticError): - """Second argument to a division or modulo operation was zero.""" - pass - -class LookupError(StandardError): - """Base class for lookup errors.""" - pass - -class IndexError(LookupError): - """Sequence index out of range.""" - pass - -class KeyError(LookupError): - """Mapping key not found.""" - pass - -class AttributeError(StandardError): - """Attribute not found.""" - pass - -class NameError(StandardError): - """Name not found globally.""" - pass - -class UnboundLocalError(NameError): - """Local name referenced but not bound to a value.""" - pass - -class UnicodeError(ValueError): - """Unicode related error.""" - pass - -class MemoryError(StandardError): - """Out of memory.""" - pass - -class SystemExit(Exception): - """Request to exit from the interpreter.""" - def __init__(self, *args): - self.args = args - if len(args) == 0: - self.code = None - elif len(args) == 1: - self.code = args[0] - else: - self.code = args diff --git a/Lib/dos-8x3/string_t.py b/Lib/dos-8x3/string_t.py new file mode 100644 index 0000000..d4041be --- /dev/null +++ b/Lib/dos-8x3/string_t.py @@ -0,0 +1,202 @@ +"""Common tests shared by test_string and test_userstring""" + +import string + +transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' + +from UserList import UserList + +class Sequence: + def __init__(self): self.seq = 'wxyz' + def __len__(self): return len(self.seq) + def __getitem__(self, i): return self.seq[i] + +class BadSeq1(Sequence): + def __init__(self): self.seq = [7, 'hello', 123L] + +class BadSeq2(Sequence): + def __init__(self): self.seq = ['a', 'b', 'c'] + def __len__(self): return 8 + +def run_module_tests(test): + """Run all tests that exercise a function in the string module""" + + test('atoi', " 1 ", 1) + test('atoi', " 1x", ValueError) + test('atoi', " x1 ", ValueError) + test('atol', " 1 ", 1L) + test('atol', " 1x ", ValueError) + test('atol', " x1 ", ValueError) + test('atof', " 1 ", 1.0) + test('atof', " 1x ", ValueError) + test('atof', " x1 ", ValueError) + + test('maketrans', 'abc', transtable, 'xyz') + test('maketrans', 'abc', ValueError, 'xyzq') + + # join now works with any sequence type + test('join', ['a', 'b', 'c', 'd'], 'a b c d') + test('join', ('a', 'b', 'c', 'd'), 'abcd', '') + test('join', Sequence(), 'w x y z') + test('join', 7, TypeError) + + test('join', BadSeq1(), TypeError) + test('join', BadSeq2(), 'a b c') + + # try a few long ones + print string.join(['x' * 100] * 100, ':') + print string.join(('x' * 100,) * 100, ':') + + +def run_method_tests(test): + """Run all tests that exercise a method of a string object""" + + test('capitalize', ' hello ', ' hello ') + test('capitalize', 'hello ', 'Hello ') + test('find', 'abcdefghiabc', 0, 'abc') + test('find', 'abcdefghiabc', 9, 'abc', 1) + test('find', 'abcdefghiabc', -1, 'def', 4) + test('rfind', 'abcdefghiabc', 9, 'abc') + test('lower', 'HeLLo', 'hello') + test('lower', 'hello', 'hello') + test('upper', 'HeLLo', 'HELLO') + test('upper', 'HELLO', 'HELLO') + + test('title', ' hello ', ' Hello ') + test('title', 'hello ', 'Hello ') + test('title', "fOrMaT thIs aS titLe String", 'Format This As Title String') + test('title', "fOrMaT,thIs-aS*titLe;String", 'Format,This-As*Title;String') + test('title', "getInt", 'Getint') + + test('expandtabs', 'abc\rab\tdef\ng\thi', 'abc\rab def\ng hi') + test('expandtabs', 'abc\rab\tdef\ng\thi', 'abc\rab def\ng hi', 8) + test('expandtabs', 'abc\rab\tdef\ng\thi', 'abc\rab def\ng hi', 4) + test('expandtabs', 'abc\r\nab\tdef\ng\thi', 'abc\r\nab def\ng hi', 4) + + test('islower', 'a', 1) + test('islower', 'A', 0) + test('islower', '\n', 0) + test('islower', 'abc', 1) + test('islower', 'aBc', 0) + test('islower', 'abc\n', 1) + + test('isupper', 'a', 0) + test('isupper', 'A', 1) + test('isupper', '\n', 0) + test('isupper', 'ABC', 1) + test('isupper', 'AbC', 0) + test('isupper', 'ABC\n', 1) + + test('istitle', 'a', 0) + test('istitle', 'A', 1) + test('istitle', '\n', 0) + test('istitle', 'A Titlecased Line', 1) + test('istitle', 'A\nTitlecased Line', 1) + test('istitle', 'A Titlecased, Line', 1) + test('istitle', 'Not a capitalized String', 0) + test('istitle', 'Not\ta Titlecase String', 0) + test('istitle', 'Not--a Titlecase String', 0) + + test('isalpha', 'a', 1) + test('isalpha', 'A', 1) + test('isalpha', '\n', 0) + test('isalpha', 'abc', 1) + test('isalpha', 'aBc123', 0) + test('isalpha', 'abc\n', 0) + + test('isalnum', 'a', 1) + test('isalnum', 'A', 1) + test('isalnum', '\n', 0) + test('isalnum', '123abc456', 1) + test('isalnum', 'a1b3c', 1) + test('isalnum', 'aBc000 ', 0) + test('isalnum', 'abc\n', 0) + + # join now works with any sequence type + test('join', ' ', 'a b c d', ['a', 'b', 'c', 'd']) + test('join', '', 'abcd', ('a', 'b', 'c', 'd')) + test('join', ' ', 'w x y z', Sequence()) + test('join', 'a', 'abc', ('abc',)) + test('join', 'a', 'z', UserList(['z'])) + test('join', u'.', u'a.b.c', ['a', 'b', 'c']) + test('join', '.', u'a.b.c', [u'a', 'b', 'c']) + test('join', '.', u'a.b.c', ['a', u'b', 'c']) + test('join', '.', u'a.b.c', ['a', 'b', u'c']) + test('join', '.', TypeError, ['a', u'b', 3]) + for i in [5, 25, 125]: + test('join', '-', ((('a' * i) + '-') * i)[:-1], + ['a' * i] * i) + + test('join', ' ', TypeError, BadSeq1()) + test('join', ' ', 'a b c', BadSeq2()) + + test('splitlines', "abc\ndef\n\rghi", ['abc', 'def', '', 'ghi']) + test('splitlines', "abc\ndef\n\r\nghi", ['abc', 'def', '', 'ghi']) + test('splitlines', "abc\ndef\r\nghi", ['abc', 'def', 'ghi']) + test('splitlines', "abc\ndef\r\nghi\n", ['abc', 'def', 'ghi']) + test('splitlines', "abc\ndef\r\nghi\n\r", ['abc', 'def', 'ghi', '']) + test('splitlines', "\nabc\ndef\r\nghi\n\r", ['', 'abc', 'def', 'ghi', '']) + test('splitlines', "\nabc\ndef\r\nghi\n\r", ['\n', 'abc\n', 'def\r\n', 'ghi\n', '\r'], 1) + + test('split', 'this is the split function', + ['this', 'is', 'the', 'split', 'function']) + test('split', 'a|b|c|d', ['a', 'b', 'c', 'd'], '|') + test('split', 'a|b|c|d', ['a', 'b', 'c|d'], '|', 2) + test('split', 'a b c d', ['a', 'b c d'], None, 1) + test('split', 'a b c d', ['a', 'b', 'c d'], None, 2) + test('split', 'a b c d', ['a', 'b', 'c', 'd'], None, 3) + test('split', 'a b c d', ['a', 'b', 'c', 'd'], None, 4) + test('split', 'a b c d', ['a b c d'], None, 0) + test('split', 'a b c d', ['a', 'b', 'c d'], None, 2) + test('split', 'a b c d ', ['a', 'b', 'c', 'd']) + + test('strip', ' hello ', 'hello') + test('lstrip', ' hello ', 'hello ') + test('rstrip', ' hello ', ' hello') + test('strip', 'hello', 'hello') + + test('swapcase', 'HeLLo cOmpUteRs', 'hEllO CoMPuTErS') + test('translate', 'xyzabcdef', 'xyzxyz', transtable, 'def') + + table = string.maketrans('a', 'A') + test('translate', 'abc', 'Abc', table) + test('translate', 'xyz', 'xyz', table) + + test('replace', 'one!two!three!', 'one@two!three!', '!', '@', 1) + test('replace', 'one!two!three!', 'onetwothree', '!', '') + test('replace', 'one!two!three!', 'one@two@three!', '!', '@', 2) + test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 3) + test('replace', 'one!two!three!', 'one@two@three@', '!', '@', 4) + test('replace', 'one!two!three!', 'one!two!three!', '!', '@', 0) + test('replace', 'one!two!three!', 'one@two@three@', '!', '@') + test('replace', 'one!two!three!', 'one!two!three!', 'x', '@') + test('replace', 'one!two!three!', 'one!two!three!', 'x', '@', 2) + + test('startswith', 'hello', 1, 'he') + test('startswith', 'hello', 1, 'hello') + test('startswith', 'hello', 0, 'hello world') + test('startswith', 'hello', 1, '') + test('startswith', 'hello', 0, 'ello') + test('startswith', 'hello', 1, 'ello', 1) + test('startswith', 'hello', 1, 'o', 4) + test('startswith', 'hello', 0, 'o', 5) + test('startswith', 'hello', 1, '', 5) + test('startswith', 'hello', 0, 'lo', 6) + test('startswith', 'helloworld', 1, 'lowo', 3) + test('startswith', 'helloworld', 1, 'lowo', 3, 7) + test('startswith', 'helloworld', 0, 'lowo', 3, 6) + + test('endswith', 'hello', 1, 'lo') + test('endswith', 'hello', 0, 'he') + test('endswith', 'hello', 1, '') + test('endswith', 'hello', 0, 'hello world') + test('endswith', 'helloworld', 0, 'worl') + test('endswith', 'helloworld', 1, 'worl', 3, 9) + test('endswith', 'helloworld', 1, 'world', 3, 12) + test('endswith', 'helloworld', 1, 'lowo', 1, 7) + test('endswith', 'helloworld', 1, 'lowo', 2, 7) + test('endswith', 'helloworld', 1, 'lowo', 3, 7) + test('endswith', 'helloworld', 0, 'lowo', 4, 7) + test('endswith', 'helloworld', 0, 'lowo', 3, 8) + test('endswith', 'ab', 0, 'ab', 0, 1) + test('endswith', 'ab', 0, 'ab', 0, 0) diff --git a/Lib/dos-8x3/test_aug.py b/Lib/dos-8x3/test_aug.py new file mode 100644 index 0000000..a01195e --- /dev/null +++ b/Lib/dos-8x3/test_aug.py @@ -0,0 +1,232 @@ + +# Augmented assignment test. + +x = 2 +x += 1 +x *= 2 +x **= 2 +x -= 8 +x /= 2 +x %= 12 +x &= 2 +x |= 5 +x ^= 1 + +print x + +x = [2] +x[0] += 1 +x[0] *= 2 +x[0] **= 2 +x[0] -= 8 +x[0] /= 2 +x[0] %= 12 +x[0] &= 2 +x[0] |= 5 +x[0] ^= 1 + +print x + +x = {0: 2} +x[0] += 1 +x[0] *= 2 +x[0] **= 2 +x[0] -= 8 +x[0] /= 2 +x[0] %= 12 +x[0] &= 2 +x[0] |= 5 +x[0] ^= 1 + +print x[0] + +x = [1,2] +x += [3,4] +x *= 2 + +print x + +x = [1, 2, 3] +y = x +x[1:2] *= 2 +y[1:2] += [1] + +print x +print x is y + +class aug_test: + def __init__(self, value): + self.val = value + def __radd__(self, val): + return self.val + val + def __add__(self, val): + return aug_test(self.val + val) + + +class aug_test2(aug_test): + def __iadd__(self, val): + self.val = self.val + val + return self + +class aug_test3(aug_test): + def __iadd__(self, val): + return aug_test3(self.val + val) + +x = aug_test(1) +y = x +x += 10 + +print isinstance(x, aug_test) +print y is not x +print x.val + +x = aug_test2(2) +y = x +x += 10 + +print y is x +print x.val + +x = aug_test3(3) +y = x +x += 10 + +print isinstance(x, aug_test3) +print y is not x +print x.val + +class testall: + + def __add__(self, val): + print "__add__ called" + def __radd__(self, val): + print "__radd__ called" + def __iadd__(self, val): + print "__iadd__ called" + return self + + def __sub__(self, val): + print "__sub__ called" + def __rsub__(self, val): + print "__rsub__ called" + def __isub__(self, val): + print "__isub__ called" + return self + + def __mul__(self, val): + print "__mul__ called" + def __rmul__(self, val): + print "__rmul__ called" + def __imul__(self, val): + print "__imul__ called" + return self + + def __div__(self, val): + print "__div__ called" + def __rdiv__(self, val): + print "__rdiv__ called" + def __idiv__(self, val): + print "__idiv__ called" + return self + + def __mod__(self, val): + print "__mod__ called" + def __rmod__(self, val): + print "__rmod__ called" + def __imod__(self, val): + print "__imod__ called" + return self + + def __pow__(self, val): + print "__pow__ called" + def __rpow__(self, val): + print "__rpow__ called" + def __ipow__(self, val): + print "__ipow__ called" + return self + + def __or__(self, val): + print "__or__ called" + def __ror__(self, val): + print "__ror__ called" + def __ior__(self, val): + print "__ior__ called" + return self + + def __and__(self, val): + print "__and__ called" + def __rand__(self, val): + print "__rand__ called" + def __iand__(self, val): + print "__iand__ called" + return self + + def __xor__(self, val): + print "__xor__ called" + def __rxor__(self, val): + print "__rxor__ called" + def __ixor__(self, val): + print "__ixor__ called" + return self + + def __rshift__(self, val): + print "__rshift__ called" + def __rrshift__(self, val): + print "__rrshift__ called" + def __irshift__(self, val): + print "__irshift__ called" + return self + + def __lshift__(self, val): + print "__lshift__ called" + def __rlshift__(self, val): + print "__rlshift__ called" + def __ilshift__(self, val): + print "__ilshift__ called" + return self + +x = testall() +x + 1 +1 + x +x += 1 + +x - 1 +1 - x +x -= 1 + +x * 1 +1 * x +x *= 1 + +x / 1 +1 / x +x /= 1 + +x % 1 +1 % x +x %= 1 + +x ** 1 +1 ** x +x **= 1 + +x | 1 +1 | x +x |= 1 + +x & 1 +1 & x +x &= 1 + +x ^ 1 +1 ^ x +x ^= 1 + +x >> 1 +1 >> x +x >>= 1 + +x << 1 +1 << x +x <<= 1 + diff --git a/Lib/dos-8x3/test_cla.py b/Lib/dos-8x3/test_cla.py new file mode 100644 index 0000000..1fc9971 --- /dev/null +++ b/Lib/dos-8x3/test_cla.py @@ -0,0 +1,219 @@ +"Test the functionality of Python classes implementing operators." + + +testmeths = [ + +# Binary operations + "add", + "radd", + "sub", + "rsub", + "mul", + "rmul", + "div", + "rdiv", + "mod", + "rmod", + "divmod", + "rdivmod", + "pow", + "rpow", + "rshift", + "rrshift", + "lshift", + "rlshift", + "and", + "rand", + "or", + "ror", + "xor", + "rxor", + +# List/dict operations + "contains", + "getitem", + "getslice", + "setitem", + "setslice", + "delitem", + "delslice", + +# Unary operations + "neg", + "pos", + "abs", + "int", + "long", + "float", + "oct", + "hex", + +# generic operations + "init", + "del", + ] + +# These need to return something other than None +# "coerce", +# "hash", +# "str", +# "repr", + +# These are separate because they can influence the test of other methods. +# "getattr", +# "setattr", +# "delattr", + +class AllTests: + def __coerce__(self, *args): + print "__coerce__:", args + return (self,) + args + + def __hash__(self, *args): + print "__hash__:", args + return id(self) + + def __str__(self, *args): + print "__str__:", args + return "AllTests" + + def __repr__(self, *args): + print "__repr__:", args + return "AllTests" + + def __cmp__(self, *args): + print "__cmp__:", args + return 0 + +for method in testmeths: + exec("""def __%(method)s__(self, *args): + print "__%(method)s__:", args +"""%locals(), AllTests.__dict__); + +# this also tests __init__ of course. +testme = AllTests() + +# Binary operations + +testme + 1 +1 + testme + +testme - 1 +1 - testme + +testme * 1 +1 * testme + +testme / 1 +1 / testme + +testme % 1 +1 % testme + +divmod(testme,1) +divmod(1, testme) + +testme ** 1 +1 ** testme + +testme >> 1 +1 >> testme + +testme << 1 +1 << testme + +testme & 1 +1 & testme + +testme | 1 +1 | testme + +testme ^ 1 +1 ^ testme + + +# List/dict operations + +1 in testme + +testme[1] +testme[1] = 1 +del testme[1] + +testme[:42] +testme[:42] = "The Answer" +del testme[:42] + +testme[2:1024:10] +testme[2:1024:10] = "A lot" +del testme[2:1024:10] + +testme[:42, ..., :24:, 24, 100] +testme[:42, ..., :24:, 24, 100] = "Strange" +del testme[:42, ..., :24:, 24, 100] + + +# Now remove the slice hooks to see if converting normal slices to slice +# object works. + +del AllTests.__getslice__ +del AllTests.__setslice__ +del AllTests.__delslice__ + +testme[:42] +testme[:42] = "The Answer" +del testme[:42] + + +# Unary operations + +-testme ++testme +abs(testme) +int(testme) +long(testme) +float(testme) +oct(testme) +hex(testme) + + +# And the rest... + +hash(testme) +repr(testme) +str(testme) + +testme == 1 +testme < 1 +testme > 1 +testme <> 1 +testme != 1 +1 == testme +1 < testme +1 > testme +1 <> testme +1 != testme + +# This test has to be last (duh.) + +del testme + + +# Interfering tests + +class ExtraTests: + def __getattr__(self, *args): + print "__getattr__:", args + return "SomeVal" + + def __setattr__(self, *args): + print "__setattr__:", args + + def __delattr__(self, *args): + print "__delattr__:", args + +testme = ExtraTests() +testme.spam +testme.eggs = "spam, spam, spam and ham" +del testme.cardinal + diff --git a/Lib/dos-8x3/test_com.py b/Lib/dos-8x3/test_com.py new file mode 100644 index 0000000..8905864 --- /dev/null +++ b/Lib/dos-8x3/test_com.py @@ -0,0 +1,16 @@ +from test_support import verbose, TestFailed + +if verbose: + print 'Running test on duplicate arguments' + +try: + exec('def f(a, a): pass') + raise TestFailed, "duplicate arguments" +except SyntaxError: + pass + +try: + exec('def f(a = 0, a = 1): pass') + raise TestFailed, "duplicate keyword arguments" +except SyntaxError: + pass diff --git a/Lib/dos-8x3/test_coo.py b/Lib/dos-8x3/test_coo.py new file mode 100644 index 0000000..a275cf2 --- /dev/null +++ b/Lib/dos-8x3/test_coo.py @@ -0,0 +1,40 @@ + +# Simple test suite for Cookie.py + +import Cookie + +# Currently this only tests SimpleCookie + +cases = [ + ('chips=ahoy; vienna=finger', {'chips':'ahoy', 'vienna':'finger'}), + ('keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;";', + {'keebler' : 'E=mc2; L="Loves"; fudge=\012;'}), + ] + +for data, dict in cases: + C = Cookie.SimpleCookie() ; C.load(data) + print repr(C) + print str(C) + for k, v in dict.items(): + print ' ', k, repr( C[k].value ), repr(v) + assert C[k].value == v + print C[k] + +C = Cookie.SimpleCookie() +C.load('Customer="WILE_E_COYOTE"; Version=1; Path=/acme') + +assert C['Customer'].value == 'WILE_E_COYOTE' +assert C['Customer']['version'] == '1' +assert C['Customer']['path'] == '/acme' + +print C.output(['path']) +print C.js_output() +print C.js_output(['path']) + +# Try cookie with quoted meta-data +C = Cookie.SimpleCookie() +C.load('Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"') +assert C['Customer'].value == 'WILE_E_COYOTE' +assert C['Customer']['version'] == '1' +assert C['Customer']['path'] == '/acme' + diff --git a/Lib/dos-8x3/test_dos.py b/Lib/dos-8x3/test_dos.py new file mode 100644 index 0000000..ffa3ef7 --- /dev/null +++ b/Lib/dos-8x3/test_dos.py @@ -0,0 +1,49 @@ +import dospath +import string +import os + +errors = 0 + +def tester(fn, wantResult): + fn = string.replace(fn, "\\", "\\\\") + gotResult = eval(fn) + if wantResult != gotResult: + print "error!" + print "evaluated: " + str(fn) + print "should be: " + str(wantResult) + print " returned: " + str(gotResult) + print "" + global errors + errors = errors + 1 + +tester('dospath.splitdrive("c:\\foo\\bar")', ('c:', '\\foo\\bar')) +tester('dospath.splitdrive("c:/foo/bar")', ('c:', '/foo/bar')) + +tester('dospath.split("c:\\foo\\bar")', ('c:\\foo', 'bar')) +tester('dospath.split("\\\\conky\\mountpoint\\foo\\bar")', ('\\\\conky\\mountpoint\\foo', 'bar')) + +tester('dospath.split("c:\\")', ('c:\\', '')) +tester('dospath.split("\\\\conky\\mountpoint\\")', ('\\\\conky\\mountpoint', '')) + +tester('dospath.split("c:/")', ('c:/', '')) +tester('dospath.split("//conky/mountpoint/")', ('//conky/mountpoint', '')) + +tester('dospath.isabs("c:\\")', 1) +tester('dospath.isabs("\\\\conky\\mountpoint\\")', 1) +tester('dospath.isabs("\\foo")', 1) +tester('dospath.isabs("\\foo\\bar")', 1) + +tester('dospath.abspath("C:\\")', "C:\\") + +tester('dospath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])', + "/home/swen") +tester('dospath.commonprefix(["\\home\\swen\\spam", "\\home\\swen\\eggs"])', + "\\home\\swen\\") +tester('dospath.commonprefix(["/home/swen/spam", "/home/swen/spam"])', + "/home/swen/spam") + +if errors: + print str(errors) + " errors." +else: + print "No errors. Thank your lucky stars." + diff --git a/Lib/dos-8x3/test_fil.py b/Lib/dos-8x3/test_fil.py new file mode 100644 index 0000000..4ad5c95 --- /dev/null +++ b/Lib/dos-8x3/test_fil.py @@ -0,0 +1,45 @@ +from test_support import TESTFN +from UserList import UserList + +# verify writelines with instance sequence +l = UserList(['1', '2']) +f = open(TESTFN, 'wb') +f.writelines(l) +f.close() +f = open(TESTFN, 'rb') +buf = f.read() +f.close() +assert buf == '12' + +# verify writelines with integers +f = open(TESTFN, 'wb') +try: + f.writelines([1, 2, 3]) +except TypeError: + pass +else: + print "writelines accepted sequence of integers" +f.close() + +# verify writelines with integers in UserList +f = open(TESTFN, 'wb') +l = UserList([1,2,3]) +try: + f.writelines(l) +except TypeError: + pass +else: + print "writelines accepted sequence of integers" +f.close() + +# verify writelines with non-string object +class NonString: pass + +f = open(TESTFN, 'wb') +try: + f.writelines([NonString(), NonString()]) +except TypeError: + pass +else: + print "writelines accepted sequence of non-string objects" +f.close() diff --git a/Lib/dos-8x3/test_get.py b/Lib/dos-8x3/test_get.py new file mode 100644 index 0000000..3927c1c --- /dev/null +++ b/Lib/dos-8x3/test_get.py @@ -0,0 +1,101 @@ +# test_getopt.py +# David Goodger <dgoodger@bigfoot.com> 2000-08-19 + +import getopt +from getopt import GetoptError +from test_support import verbose + +def expectException(teststr, expected, failure=AssertionError): + """Executes a statement passed in teststr, and raises an exception + (failure) if the expected exception is *not* raised.""" + try: + exec teststr + except expected: + pass + else: + raise failure + +if verbose: + print 'Running tests on getopt.short_has_arg' +assert getopt.short_has_arg('a', 'a:') +assert not getopt.short_has_arg('a', 'a') +expectException("tmp = getopt.short_has_arg('a', 'b')", GetoptError) +expectException("tmp = getopt.short_has_arg('a', '')", GetoptError) + +if verbose: + print 'Running tests on getopt.long_has_args' +has_arg, option = getopt.long_has_args('abc', ['abc=']) +assert has_arg +assert option == 'abc' +has_arg, option = getopt.long_has_args('abc', ['abc']) +assert not has_arg +assert option == 'abc' +has_arg, option = getopt.long_has_args('abc', ['abcd']) +assert not has_arg +assert option == 'abcd' +expectException("has_arg, option = getopt.long_has_args('abc', ['def'])", + GetoptError) +expectException("has_arg, option = getopt.long_has_args('abc', [])", + GetoptError) +expectException("has_arg, option = " + \ + "getopt.long_has_args('abc', ['abcd','abcde'])", + GetoptError) + +if verbose: + print 'Running tests on getopt.do_shorts' +opts, args = getopt.do_shorts([], 'a', 'a', []) +assert opts == [('-a', '')] +assert args == [] +opts, args = getopt.do_shorts([], 'a1', 'a:', []) +assert opts == [('-a', '1')] +assert args == [] +#opts, args = getopt.do_shorts([], 'a=1', 'a:', []) +#assert opts == [('-a', '1')] +#assert args == [] +opts, args = getopt.do_shorts([], 'a', 'a:', ['1']) +assert opts == [('-a', '1')] +assert args == [] +opts, args = getopt.do_shorts([], 'a', 'a:', ['1', '2']) +assert opts == [('-a', '1')] +assert args == ['2'] +expectException("opts, args = getopt.do_shorts([], 'a1', 'a', [])", + GetoptError) +expectException("opts, args = getopt.do_shorts([], 'a', 'a:', [])", + GetoptError) + +if verbose: + print 'Running tests on getopt.do_longs' +opts, args = getopt.do_longs([], 'abc', ['abc'], []) +assert opts == [('--abc', '')] +assert args == [] +opts, args = getopt.do_longs([], 'abc=1', ['abc='], []) +assert opts == [('--abc', '1')] +assert args == [] +opts, args = getopt.do_longs([], 'abc=1', ['abcd='], []) +assert opts == [('--abcd', '1')] +assert args == [] +expectException("opts, args = getopt.do_longs([], 'abc=1', ['abc'], [])", + GetoptError) +expectException("opts, args = getopt.do_longs([], 'abc', ['abc='], [])", + GetoptError) + +# note: the empty string between '-a' and '--beta' is significant: +# it simulates an empty string option argument ('-a ""') on the command line. +cmdline = ['-a', '1', '-b', '--alpha=2', '--beta', '-a', '3', '-a', '', + '--beta', 'arg1', 'arg2'] + +if verbose: + print 'Running tests on getopt.getopt' +opts, args = getopt.getopt(cmdline, 'a:b', ['alpha=', 'beta']) +assert opts == [('-a', '1'), ('-b', ''), ('--alpha', '2'), ('--beta', ''), + ('-a', '3'), ('-a', ''), ('--beta', '')] +# Note ambiguity of ('-b', '') and ('-a', '') above. This must be +# accounted for in the code that calls getopt(). +assert args == ['arg1', 'arg2'] + +expectException( + "opts, args = getopt.getopt(cmdline, 'a:b', ['alpha', 'beta'])", + GetoptError) + +if verbose: + print "Module getopt: tests completed successfully." diff --git a/Lib/dos-8x3/test_lar.py b/Lib/dos-8x3/test_lar.py new file mode 100644 index 0000000..5b65237 --- /dev/null +++ b/Lib/dos-8x3/test_lar.py @@ -0,0 +1,129 @@ +#!python + +#---------------------------------------------------------------------- +# test largefile support on system where this makes sense +# +#XXX how to only run this when support is there +#XXX how to only optionally run this, it will take along time +#---------------------------------------------------------------------- + +import test_support +import os, struct, stat, sys + + +# only run if the current system support large files +f = open(test_support.TESTFN, 'w') +try: + # 2**31 == 2147483648 + f.seek(2147483649L) +except OverflowError: + raise test_support.TestSkipped, "platform does not have largefile support" +else: + f.close() + + +# create >2GB file (2GB = 2147483648 bytes) +size = 2500000000L +name = test_support.TESTFN + + +# on Windows this test comsumes large resources: +# it takes a long time to build the >2GB file and takes >2GB of disk space +# therefore test_support.use_large_resources must be defined to run this test +if sys.platform[:3] == 'win' and not test_support.use_large_resources: + raise test_support.TestSkipped, \ + "test requires %s bytes and a long time to run" % str(size) + + + +def expect(got_this, expect_this): + if test_support.verbose: + print '%s =?= %s ...' % (`got_this`, `expect_this`), + if got_this != expect_this: + if test_support.verbose: + print 'no' + raise test_support.TestFailed, 'got %s, but expected %s' %\ + (str(got_this), str(expect_this)) + else: + if test_support.verbose: + print 'yes' + + +# test that each file function works as expected for a large (i.e. >2GB, do +# we have to check >4GB) files + +if test_support.verbose: + print 'create large file via seek (may be sparse file) ...' +f = open(name, 'w') +f.seek(size) +f.write('a') +f.flush() +expect(os.fstat(f.fileno())[stat.ST_SIZE], size+1) +if test_support.verbose: + print 'check file size with os.fstat' +f.close() +if test_support.verbose: + print 'check file size with os.stat' +expect(os.stat(name)[stat.ST_SIZE], size+1) + +if test_support.verbose: + print 'play around with seek() and read() with the built largefile' +f = open(name, 'r') +expect(f.tell(), 0) +expect(f.read(1), '\000') +expect(f.tell(), 1) +f.seek(0) +expect(f.tell(), 0) +f.seek(0, 0) +expect(f.tell(), 0) +f.seek(42) +expect(f.tell(), 42) +f.seek(42, 0) +expect(f.tell(), 42) +f.seek(42, 1) +expect(f.tell(), 84) +f.seek(0, 1) +expect(f.tell(), 84) +f.seek(0, 2) # seek from the end +expect(f.tell(), size + 1 + 0) +f.seek(-10, 2) +expect(f.tell(), size + 1 - 10) +f.seek(-size-1, 2) +expect(f.tell(), 0) +f.seek(size) +expect(f.tell(), size) +expect(f.read(1), 'a') # the 'a' that was written at the end of the file above +f.close() + +if test_support.verbose: + print 'play around with os.lseek() with the built largefile' +f = open(name, 'r') +expect(os.lseek(f.fileno(), 0, 0), 0) +expect(os.lseek(f.fileno(), 42, 0), 42) +expect(os.lseek(f.fileno(), 42, 1), 84) +expect(os.lseek(f.fileno(), 0, 1), 84) +expect(os.lseek(f.fileno(), 0, 2), size+1+0) +expect(os.lseek(f.fileno(), -10, 2), size+1-10) +expect(os.lseek(f.fileno(), -size-1, 2), 0) +expect(os.lseek(f.fileno(), size, 0), size) +expect(f.read(1), 'a') # the 'a' that was written at the end of the file above +f.close() + + +# XXX add tests for truncate if it exists +# XXX has truncate ever worked on Windows? specifically on WinNT I get: +# "IOError: [Errno 13] Permission denied" +##try: +## newsize = size - 10 +## f.seek(newsize) +## f.truncate() +## expect(f.tell(), newsize) +## newsize = newsize - 1 +## f.seek(0) +## f.truncate(newsize) +## expect(f.tell(), newsize) +##except AttributeError: +## pass + +os.unlink(name) + diff --git a/Lib/dos-8x3/test_min.py b/Lib/dos-8x3/test_min.py new file mode 100644 index 0000000..73c8ac4 --- /dev/null +++ b/Lib/dos-8x3/test_min.py @@ -0,0 +1,331 @@ +# test for xml.dom.minidom + +from xml.dom.minidom import parse, Node, Document, parseString + +import os.path +import sys +import traceback + +if __name__ == "__main__": + base = sys.argv[0] +else: + base = __file__ +tstfile = os.path.join(os.path.dirname(base), "test.xml") +del base + +Node._debug=1 + +def testGetElementsByTagName( ): + dom=parse( tstfile ) + assert dom.getElementsByTagName( "LI" )==\ + dom.documentElement.getElementsByTagName( "LI" ) + dom.unlink() + dom=None + assert( len( Node.allnodes ))==0 + +def testInsertBefore( ): + dom=parse( tstfile ) + docel=dom.documentElement + #docel.insertBefore( dom.createProcessingInstruction("a", "b"), + # docel.childNodes[1]) + + #docel.insertBefore( dom.createProcessingInstruction("a", "b"), + # docel.childNodes[0]) + + #assert docel.childNodes[0].target=="a" + #assert docel.childNodes[2].target=="a" + dom.unlink() + del dom + del docel + assert( len( Node.allnodes ))==0 + +def testAppendChild(): + dom=parse( tstfile ) + dom.documentElement.appendChild( dom.createComment( u"Hello" )) + assert dom.documentElement.childNodes[-1].nodeName=="#comment" + assert dom.documentElement.childNodes[-1].data=="Hello" + dom.unlink() + dom=None + assert( len( Node.allnodes ))==0 + +def testNonZero(): + dom=parse( tstfile ) + assert dom # should not be zero + dom.appendChild( dom.createComment( "foo" ) ) + assert not dom.childNodes[-1].childNodes + dom.unlink() + dom=None + assert( len( Node.allnodes ))==0 + +def testUnlink(): + dom=parse( tstfile ) + dom.unlink() + dom=None + assert( len( Node.allnodes ))==0 + +def testElement(): + dom=Document() + dom.appendChild( dom.createElement( "abc" ) ) + assert dom.documentElement + dom.unlink() + dom=None + assert( len( Node.allnodes ))==0 + +def testAAA(): + dom=parseString( "<abc/>" ) + el=dom.documentElement + el.setAttribute( "spam", "jam2" ) + dom.unlink() + dom=None + +def testAAB(): + dom=parseString( "<abc/>" ) + el=dom.documentElement + el.setAttribute( "spam", "jam" ) + el.setAttribute( "spam", "jam2" ) + dom.unlink() + dom=None + +def testAddAttr(): + dom=Document() + child=dom.appendChild( dom.createElement( "abc" ) ) + + child.setAttribute( "def", "ghi" ) + assert child.getAttribute( "def" )=="ghi" + assert child.attributes["def"].value=="ghi" + + child.setAttribute( "jkl", "mno" ) + assert child.getAttribute( "jkl" )=="mno" + assert child.attributes["jkl"].value=="mno" + + assert len( child.attributes )==2 + + child.setAttribute( "def", "newval" ) + assert child.getAttribute( "def" )=="newval" + assert child.attributes["def"].value=="newval" + + assert len( child.attributes )==2 + + dom.unlink() + dom=None + child=None + +def testDeleteAttr(): + dom=Document() + child=dom.appendChild( dom.createElement( "abc" ) ) + + assert len( child.attributes)==0 + child.setAttribute( "def", "ghi" ) + assert len( child.attributes)==1 + del child.attributes["def"] + assert len( child.attributes)==0 + dom.unlink() + assert( len( Node.allnodes ))==0 + +def testRemoveAttr(): + dom=Document() + child=dom.appendChild( dom.createElement( "abc" ) ) + + child.setAttribute( "def", "ghi" ) + assert len( child.attributes)==1 + child.removeAttribute("def" ) + assert len( child.attributes)==0 + + dom.unlink() + +def testRemoveAttrNS(): + dom=Document() + child=dom.appendChild( + dom.createElementNS( "http://www.python.org", "python:abc" ) ) + child.setAttributeNS( "http://www.w3.org", "xmlns:python", + "http://www.python.org" ) + child.setAttributeNS( "http://www.python.org", "python:abcattr", "foo" ) + assert len( child.attributes )==2 + child.removeAttributeNS( "http://www.python.org", "abcattr" ) + assert len( child.attributes )==1 + + dom.unlink() + dom=None + +def testRemoveAttributeNode(): + dom=Document() + child=dom.appendChild( dom.createElement( "foo" ) ) + child.setAttribute( "spam", "jam" ) + assert len( child.attributes )==1 + node=child.getAttributeNode( "spam" ) + child.removeAttributeNode( node ) + assert len( child.attributes )==0 + + dom.unlink() + dom=None + assert len( Node.allnodes )==0 + +def testChangeAttr(): + dom=parseString( "<abc/>" ) + el=dom.documentElement + el.setAttribute( "spam", "jam" ) + assert len( el.attributes )==1 + el.setAttribute( "spam", "bam" ) + assert len( el.attributes )==1 + el.attributes["spam"]="ham" + assert len( el.attributes )==1 + el.setAttribute( "spam2", "bam" ) + assert len( el.attributes )==2 + el.attributes[ "spam2"]= "bam2" + assert len( el.attributes )==2 + dom.unlink() + dom=None + assert len( Node.allnodes )==0 + +def testGetAttrList(): + pass + +def testGetAttrValues(): pass + +def testGetAttrLength(): pass + +def testGetAttribute(): pass + +def testGetAttributeNS(): pass + +def testGetAttributeNode(): pass + +def testGetElementsByTagNameNS(): pass + +def testGetEmptyNodeListFromElementsByTagNameNS(): pass + +def testElementReprAndStr(): + dom=Document() + el=dom.appendChild( dom.createElement( "abc" ) ) + string1=repr( el ) + string2=str( el ) + assert string1==string2 + dom.unlink() + +# commented out until Fredrick's fix is checked in +def _testElementReprAndStrUnicode(): + dom=Document() + el=dom.appendChild( dom.createElement( u"abc" ) ) + string1=repr( el ) + string2=str( el ) + assert string1==string2 + dom.unlink() + +# commented out until Fredrick's fix is checked in +def _testElementReprAndStrUnicodeNS(): + dom=Document() + el=dom.appendChild( + dom.createElementNS( u"http://www.slashdot.org", u"slash:abc" )) + string1=repr( el ) + string2=str( el ) + assert string1==string2 + assert string1.find("slash:abc" )!=-1 + dom.unlink() + +def testAttributeRepr(): + dom=Document() + el=dom.appendChild( dom.createElement( u"abc" ) ) + node=el.setAttribute( "abc", "def" ) + assert str( node ) == repr( node ) + dom.unlink() + +def testTextNodeRepr(): pass + +def testWriteXML(): pass + +def testProcessingInstruction(): pass + +def testProcessingInstructionRepr(): pass + +def testTextRepr(): pass + +def testWriteText(): pass + +def testDocumentElement(): pass + +def testTooManyDocumentElements(): pass + +def testCreateElementNS(): pass + +def testCreatAttributeNS(): pass + +def testParse(): pass + +def testParseString(): pass + +def testComment(): pass + +def testAttrListItem(): pass + +def testAttrListItems(): pass + +def testAttrListItemNS(): pass + +def testAttrListKeys(): pass + +def testAttrListKeysNS(): pass + +def testAttrListValues(): pass + +def testAttrListLength(): pass + +def testAttrList__getitem__(): pass + +def testAttrList__setitem__(): pass + +def testSetAttrValueandNodeValue(): pass + +def testParseElement(): pass + +def testParseAttributes(): pass + +def testParseElementNamespaces(): pass + +def testParseAttributeNamespaces(): pass + +def testParseProcessingInstructions(): pass + +def testChildNodes(): pass + +def testFirstChild(): pass + +def testHasChildNodes(): pass + +def testCloneElementShallow(): pass + +def testCloneElementShallowCopiesAttributes(): pass + +def testCloneElementDeep(): pass + +def testCloneDocumentShallow(): pass + +def testCloneDocumentDeep(): pass + +def testCloneAttributeShallow(): pass + +def testCloneAttributeDeep(): pass + +def testClonePIShallow(): pass + +def testClonePIDeep(): pass + + +names=globals().keys() +names.sort() +for name in names: + if name.startswith( "test" ): + func=globals()[name] + try: + func() + print "Test Succeeded", name + if len( Node.allnodes ): + print "Garbage left over:" + print Node.allnodes.items()[0:10] + Node.allnodes={} + except Exception, e : + print "Test Failed: ", name + apply( traceback.print_exception, sys.exc_info() ) + print `e` + Node.allnodes={} + raise + diff --git a/Lib/dos-8x3/test_par.py b/Lib/dos-8x3/test_par.py new file mode 100644 index 0000000..bc41de4 --- /dev/null +++ b/Lib/dos-8x3/test_par.py @@ -0,0 +1,178 @@ +import os.path +import parser +import pprint +import sys + +from parser import expr, suite, sequence2ast +from test_support import verbose + +# +# First, we test that we can generate trees from valid source fragments, +# and that these valid trees are indeed allowed by the tree-loading side +# of the parser module. +# + +def roundtrip(f, s): + st1 = f(s) + t = st1.totuple() + st2 = parser.sequence2ast(t) + +def roundtrip_fromfile(filename): + roundtrip(suite, open(filename).read()) + +def test_expr(s): + print "expr:", s + roundtrip(expr, s) + +def test_suite(s): + print "suite:", s + roundtrip(suite, s) + + +print "Expressions:" + +test_expr("foo(1)") +test_expr("[1, 2, 3]") +test_expr("[x**3 for x in range(20)]") +test_expr("[x**3 for x in range(20) if x % 3]") +test_expr("foo(*args)") +test_expr("foo(*args, **kw)") +test_expr("foo(**kw)") +test_expr("foo(key=value)") +test_expr("foo(key=value, *args)") +test_expr("foo(key=value, *args, **kw)") +test_expr("foo(key=value, **kw)") +test_expr("foo(a, b, c, *args)") +test_expr("foo(a, b, c, *args, **kw)") +test_expr("foo(a, b, c, **kw)") +test_expr("foo + bar") + +print +print "Statements:" +test_suite("print") +test_suite("print 1") +test_suite("print 1,") +test_suite("print >>fp") +test_suite("print >>fp, 1") +test_suite("print >>fp, 1,") + +# expr_stmt +test_suite("a") +test_suite("a = b") +test_suite("a = b = c = d = e") +test_suite("a += b") +test_suite("a -= b") +test_suite("a *= b") +test_suite("a /= b") +test_suite("a %= b") +test_suite("a &= b") +test_suite("a |= b") +test_suite("a ^= b") +test_suite("a <<= b") +test_suite("a >>= b") +test_suite("a **= b") + +#d = os.path.dirname(os.__file__) +#roundtrip_fromfile(os.path.join(d, "os.py")) +#roundtrip_fromfile(os.path.join(d, "test", "test_parser.py")) + +# +# Second, we take *invalid* trees and make sure we get ParserError +# rejections for them. +# + +print +print "Invalid parse trees:" + +def check_bad_tree(tree, label): + print + print label + try: + sequence2ast(tree) + except parser.ParserError: + print "caught expected exception for invalid tree" + pass + else: + print "test failed: did not properly detect invalid tree:" + pprint.pprint(tree) + + +# not even remotely valid: +check_bad_tree((1, 2, 3), "<junk>") + +# print >>fp, +tree = \ +(257, + (264, + (265, + (266, + (268, + (1, 'print'), + (35, '>>'), + (290, + (291, + (292, + (293, + (295, + (296, + (297, + (298, (299, (300, (301, (302, (303, (1, 'fp')))))))))))))), + (12, ','))), + (4, ''))), + (0, '')) + +check_bad_tree(tree, "print >>fp,") + +# a,,c +tree = \ +(258, + (311, + (290, + (291, + (292, + (293, + (295, + (296, (297, (298, (299, (300, (301, (302, (303, (1, 'a')))))))))))))), + (12, ','), + (12, ','), + (290, + (291, + (292, + (293, + (295, + (296, (297, (298, (299, (300, (301, (302, (303, (1, 'c'))))))))))))))), + (4, ''), + (0, '')) + +check_bad_tree(tree, "a,,c") + +# a $= b +tree = \ +(257, + (264, + (265, + (266, + (267, + (312, + (291, + (292, + (293, + (294, + (296, + (297, + (298, + (299, (300, (301, (302, (303, (304, (1, 'a'))))))))))))))), + (268, (37, '$=')), + (312, + (291, + (292, + (293, + (294, + (296, + (297, + (298, + (299, (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))), + (4, ''))), + (0, '')) + +check_bad_tree(tree, "a $= b") diff --git a/Lib/dos-8x3/test_pol.py b/Lib/dos-8x3/test_pol.py new file mode 100644 index 0000000..82d8372 --- /dev/null +++ b/Lib/dos-8x3/test_pol.py @@ -0,0 +1,172 @@ +# Test case for the os.poll() function + +import sys, os, select, random +from test_support import verbose, TestSkipped, TESTFN + +try: + select.poll +except AttributeError: + raise TestSkipped, "select.poll not defined -- skipping test_poll" + + +def find_ready_matching(ready, flag): + match = [] + for fd, mode in ready: + if mode & flag: + match.append(fd) + return match + +def test_poll1(): + """Basic functional test of poll object + + Create a bunch of pipe and test that poll works with them. + """ + print 'Running poll test 1' + p = select.poll() + + NUM_PIPES = 12 + MSG = " This is a test." + MSG_LEN = len(MSG) + readers = [] + writers = [] + r2w = {} + w2r = {} + + for i in range(NUM_PIPES): + rd, wr = os.pipe() + p.register(rd, select.POLLIN) + p.register(wr, select.POLLOUT) + readers.append(rd) + writers.append(wr) + r2w[rd] = wr + w2r[wr] = rd + + while writers: + ready = p.poll() + ready_writers = find_ready_matching(ready, select.POLLOUT) + if not ready_writers: + raise RuntimeError, "no pipes ready for writing" + wr = random.choice(ready_writers) + os.write(wr, MSG) + + ready = p.poll() + ready_readers = find_ready_matching(ready, select.POLLIN) + if not ready_readers: + raise RuntimeError, "no pipes ready for reading" + rd = random.choice(ready_readers) + buf = os.read(rd, MSG_LEN) + assert len(buf) == MSG_LEN + print buf + os.close(r2w[rd]) ; os.close( rd ) + p.unregister( r2w[rd] ) + p.unregister( rd ) + writers.remove(r2w[rd]) + + poll_unit_tests() + print 'Poll test 1 complete' + +def poll_unit_tests(): + # returns NVAL for invalid file descriptor + FD = 42 + try: + os.close(FD) + except OSError: + pass + p = select.poll() + p.register(FD) + r = p.poll() + assert r[0] == (FD, select.POLLNVAL) + + f = open(TESTFN, 'w') + fd = f.fileno() + p = select.poll() + p.register(f) + r = p.poll() + assert r[0][0] == fd + f.close() + r = p.poll() + assert r[0] == (fd, select.POLLNVAL) + os.unlink(TESTFN) + + # type error for invalid arguments + p = select.poll() + try: + p.register(p) + except TypeError: + pass + else: + print "Bogus register call did not raise TypeError" + try: + p.unregister(p) + except TypeError: + pass + else: + print "Bogus unregister call did not raise TypeError" + + # can't unregister non-existent object + p = select.poll() + try: + p.unregister(3) + except KeyError: + pass + else: + print "Bogus unregister call did not raise KeyError" + + # Test error cases + pollster = select.poll() + class Nope: + pass + + class Almost: + def fileno(self): + return 'fileno' + + try: + pollster.register( Nope(), 0 ) + except TypeError: pass + else: print 'expected TypeError exception, not raised' + + try: + pollster.register( Almost(), 0 ) + except TypeError: pass + else: print 'expected TypeError exception, not raised' + + +# Another test case for poll(). This is copied from the test case for +# select(), modified to use poll() instead. + +def test_poll2(): + print 'Running poll test 2' + cmd = 'for i in 0 1 2 3 4 5 6 7 8 9; do echo testing...; sleep 1; done' + p = os.popen(cmd, 'r') + pollster = select.poll() + pollster.register( p, select.POLLIN ) + for tout in (0, 1000, 2000, 4000, 8000, 16000) + (-1,)*10: + if verbose: + print 'timeout =', tout + fdlist = pollster.poll(tout) + if (fdlist == []): + continue + fd, flags = fdlist[0] + if flags & select.POLLHUP: + line = p.readline() + if line != "": + print 'error: pipe seems to be closed, but still returns data' + continue + + elif flags & select.POLLIN: + line = p.readline() + if verbose: + print `line` + if not line: + if verbose: + print 'EOF' + break + continue + else: + print 'Unexpected return value from select.poll:', fdlist + p.close() + print 'Poll test 2 complete' + +test_poll1() +test_poll2() diff --git a/Lib/dos-8x3/test_pos.py b/Lib/dos-8x3/test_pos.py new file mode 100644 index 0000000..27bee61 --- /dev/null +++ b/Lib/dos-8x3/test_pos.py @@ -0,0 +1,42 @@ +import posixpath +import string + +errors = 0 + +def tester(fn, wantResult): + gotResult = eval(fn) + if wantResult != gotResult: + print "error!" + print "evaluated: " + str(fn) + print "should be: " + str(wantResult) + print " returned: " + str(gotResult) + print "" + global errors + errors = errors + 1 + +tester('posixpath.splitdrive("/foo/bar")', ('', '/foo/bar')) + +tester('posixpath.split("/foo/bar")', ('/foo', 'bar')) +tester('posixpath.split("/")', ('/', '')) +tester('posixpath.split("foo")', ('', 'foo')) + +tester('posixpath.splitext("foo.ext")', ('foo', '.ext')) +tester('posixpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext')) + +tester('posixpath.isabs("/")', 1) +tester('posixpath.isabs("/foo")', 1) +tester('posixpath.isabs("/foo/bar")', 1) +tester('posixpath.isabs("foo/bar")', 0) + +tester('posixpath.commonprefix(["/home/swenson/spam", "/home/swen/spam"])', + "/home/swen") +tester('posixpath.commonprefix(["/home/swen/spam", "/home/swen/eggs"])', + "/home/swen/") +tester('posixpath.commonprefix(["/home/swen/spam", "/home/swen/spam"])', + "/home/swen/spam") + +if errors: + print str(errors) + " errors." +else: + print "No errors. Thank your lucky stars." + diff --git a/Lib/dos-8x3/test_url.py b/Lib/dos-8x3/test_url.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Lib/dos-8x3/test_url.py diff --git a/Lib/dos-8x3/threadst.py b/Lib/dos-8x3/threadst.py deleted file mode 100644 index d9c2788..0000000 --- a/Lib/dos-8x3/threadst.py +++ /dev/null @@ -1,9 +0,0 @@ -import thread -# Start empty thread to initialize thread mechanics (and global lock!) -# This thread will finish immediately thus won't make much influence on -# test results by itself, only by that fact that it initializes global lock -thread.start_new_thread(lambda : 1, ()) - -import test.pystone -test.pystone.main() - diff --git a/Lib/dos-8x3/webbrows.py b/Lib/dos-8x3/webbrows.py new file mode 100644 index 0000000..5a4a80f --- /dev/null +++ b/Lib/dos-8x3/webbrows.py @@ -0,0 +1,229 @@ +"""Remote-control interfaces to some browsers.""" + +import os +import sys + + +PROCESS_CREATION_DELAY = 4 + + +class Error(Exception): + pass + + +_browsers = {} + +def register(name, klass, instance=None): + """Register a browser connector and, optionally, connection.""" + _browsers[name.lower()] = [klass, instance] + + +def get(name=None): + """Retrieve a connection to a browser by type name, or the default + browser.""" + name = name or DEFAULT_BROWSER + try: + L = _browsers[name.lower()] + except KeyError: + raise ValueError, "unknown browser type: " + `name` + if L[1] is None: + L[1] = L[0]() + return L[1] + + +# Please note: the following definition hides a builtin function. + +def open(url, new=0): + get().open(url, new) + + +def open_new(url): + get().open_new(url) + + +def _iscommand(cmd): + """Return true if cmd can be found on the executable search path.""" + path = os.environ.get("PATH") + if not path: + return 0 + for d in path.split(os.pathsep): + exe = os.path.join(d, cmd) + if os.path.isfile(exe): + return 1 + return 0 + + +class CommandLineBrowser: + _browsers = [] + if os.environ.get("DISPLAY"): + _browsers.extend([ + ("netscape", "netscape %s >/dev/null &"), + ("mosaic", "mosaic %s >/dev/null &"), + ]) + _browsers.extend([ + ("lynx", "lynx %s"), + ("w3m", "w3m %s"), + ]) + + def open(self, url, new=0): + for exe, cmd in self._browsers: + if _iscommand(exe): + os.system(cmd % url) + return + raise Error("could not locate runnable browser") + + def open_new(self, url): + self.open(url) + +register("command-line", CommandLineBrowser) + + +class Netscape: + autoRaise = 1 + + def _remote(self, action): + raise_opt = ("-noraise", "-raise")[self.autoRaise] + cmd = "netscape %s -remote '%s' >/dev/null 2>&1" % (raise_opt, action) + rc = os.system(cmd) + if rc: + import time + os.system("netscape -no-about-splash &") + time.sleep(PROCESS_CREATION_DELAY) + rc = os.system(cmd) + return not rc + + def open(self, url, new=0): + if new: + self.open_new(url) + else: + self._remote("openURL(%s)" % url) + + def open_new(self, url): + self._remote("openURL(%s, new-window)" % url) + +register("netscape", Netscape) + + +class Konquerer: + """Controller for the KDE File Manager (kfm, or Konquerer). + + See http://developer.kde.org/documentation/other/kfmclient.html + for more information on the Konquerer remote-control interface. + + """ + def _remote(self, action): + cmd = "kfmclient %s >/dev/null 2>&1" % action + rc = os.system(cmd) + if rc: + import time + os.system("kfm -d &") + time.sleep(PROCESS_CREATION_DELAY) + rc = os.system(cmd) + return not rc + + def open(self, url, new=1): + # XXX currently I know no way to prevent KFM from opening a new win. + self.open_new(url) + + def open_new(self, url): + self._remote("openURL %s" % url) + +register("kfm", Konquerer) + + +class Grail: + # There should be a way to maintain a connection to Grail, but the + # Grail remote control protocol doesn't really allow that at this + # point. It probably never will! + + def _find_grail_rc(self): + import glob + import pwd + import socket + import tempfile + tempdir = os.path.join(tempfile.gettempdir(), ".grail-unix") + user = pwd.getpwuid(_os.getuid())[0] + filename = os.path.join(tempdir, user + "-*") + maybes = glob.glob(filename) + if not maybes: + return None + s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + for fn in maybes: + # need to PING each one until we find one that's live + try: + s.connect(fn) + except socket.error: + # no good; attempt to clean it out, but don't fail: + try: + os.unlink(fn) + except IOError: + pass + else: + return s + + def _remote(self, action): + s = self._find_grail_rc() + if not s: + return 0 + s.send(action) + s.close() + return 1 + + def open(self, url, new=0): + if new: + self.open_new(url) + else: + self._remote("LOAD " + url) + + def open_new(self, url): + self._remote("LOADNEW " + url) + +register("grail", Grail) + + +class WindowsDefault: + def open(self, url, new=0): + import win32api, win32con + win32api.ShellExecute(0, "open", url, None, ".", + win32con.SW_SHOWNORMAL) + + def open_new(self, url): + self.open(url) + + +DEFAULT_BROWSER = "command-line" + +if sys.platform[:3] == "win": + del _browsers["kfm"] + register("windows-default", WindowsDefault) + DEFAULT_BROWSER = "windows-default" +elif os.environ.get("DISPLAY"): + if os.environ.get("KDEDIR"): + DEFAULT_BROWSER = "kfm" + elif _iscommand("netscape"): + DEFAULT_BROWSER = "netscape" + +# If the $BROWSER environment variable is set and true, let that be +# the name of the browser to use: +# +DEFAULT_BROWSER = os.environ.get("BROWSER") or DEFAULT_BROWSER + + +# Now try to support the MacOS world. This is the only supported +# controller on that platform, so don't mess with the default! + +try: + import ic +except ImportError: + pass +else: + class InternetConfig: + def open(self, url, new=0): + ic.launcurl(url) + + def open_new(self, url): + self.open(url) + + _browsers.clear() + register("internet-config", InternetConfig) + DEFAULT_BROWSER = "internet-config" |