diff --git a/Lib/netrc.py b/Lib/netrc.py index 679669fb409..6bc0292a223 100644 --- a/Lib/netrc.py +++ b/Lib/netrc.py @@ -1,6 +1,6 @@ """An object-oriented interface to .netrc files.""" -# Module and documentation by Eric S. Raymond, 21 Dec 1998 +# Module and documentation by Eric S. Raymond, 21 Dec 1998 import os, shlex @@ -12,7 +12,7 @@ class netrc: self.hosts = {} self.macros = {} lexer = shlex.shlex(fp) - # Allows @ in hostnames. Not a big deal... + # Allows @ in hostnames. Not a big deal... lexer.wordchars = lexer.wordchars + '.-@' while 1: # Look for a machine, default, or macdef top-level keyword @@ -23,7 +23,7 @@ class netrc: entryname = lexer.get_token() elif tt == 'default': entryname = 'default' - elif tt == 'macdef': # Just skip to end of macdefs + elif tt == 'macdef': # Just skip to end of macdefs entryname = lexer.get_token() self.macros[entryname] = [] lexer.whitepace = ' \t' @@ -36,7 +36,7 @@ class netrc: self.macros[entryname].append(line) else: raise SyntaxError, "bad toplevel token %s, file %s, line %d" \ - % (tt, file, lexer.lineno) + % (tt, file, lexer.lineno) # We're looking at start of an entry for a named machine or default. if toplevel == 'machine': @@ -87,6 +87,5 @@ class netrc: rep = rep + "\n" return rep -if __name__ == '__main__': +if __name__ == '__main__': print netrc() - diff --git a/Lib/nntplib.py b/Lib/nntplib.py index 526677a95cf..16716ec5f9f 100644 --- a/Lib/nntplib.py +++ b/Lib/nntplib.py @@ -34,36 +34,36 @@ import socket import string - + # Exceptions raised when an error or invalid response is received class NNTPError(Exception): - """Base class for all nntplib exceptions""" - def __init__(self, *args): - apply(Exception.__init__, (self,)+args) - try: - self.response = args[0] - except IndexError: - self.response = 'No response given' + """Base class for all nntplib exceptions""" + def __init__(self, *args): + apply(Exception.__init__, (self,)+args) + try: + self.response = args[0] + except IndexError: + self.response = 'No response given' class NNTPReplyError(NNTPError): - """Unexpected [123]xx reply""" - pass + """Unexpected [123]xx reply""" + pass class NNTPTemporaryError(NNTPError): - """4xx errors""" - pass + """4xx errors""" + pass class NNTPPermanentError(NNTPError): - """5xx errors""" - pass + """5xx errors""" + pass class NNTPProtocolError(NNTPError): - """Response does not begin with [1-5]""" - pass + """Response does not begin with [1-5]""" + pass class NNTPDataError(NNTPError): - """Error in response data""" - pass + """Error in response data""" + pass # for backwards compatibility error_reply = NNTPReplyError @@ -73,7 +73,7 @@ error_proto = NNTPProtocolError error_data = NNTPDataError - + # Standard port used by NNTP servers NNTP_PORT = 119 @@ -86,450 +86,450 @@ LONGRESP = ['100', '215', '220', '221', '222', '224', '230', '231', '282'] CRLF = '\r\n' - + # The class itself class NNTP: - def __init__(self, host, port=NNTP_PORT, user=None, password=None, - readermode=None): - """Initialize an instance. Arguments: - - host: hostname to connect to - - port: port to connect to (default the standard NNTP port) - - user: username to authenticate with - - password: password to use with username - - readermode: if true, send 'mode reader' command after - connecting. + def __init__(self, host, port=NNTP_PORT, user=None, password=None, + readermode=None): + """Initialize an instance. Arguments: + - host: hostname to connect to + - port: port to connect to (default the standard NNTP port) + - user: username to authenticate with + - password: password to use with username + - readermode: if true, send 'mode reader' command after + connecting. - readermode is sometimes necessary if you are connecting to an - NNTP server on the local machine and intend to call - reader-specific comamnds, such as `group'. If you get - unexpected NNTPPermanentErrors, you might need to set - readermode. - """ - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((self.host, self.port)) - self.file = self.sock.makefile('rb') - self.debugging = 0 - self.welcome = self.getresp() - if readermode: - try: - self.welcome = self.shortcmd('mode reader') - except NNTPPermanentError: - # error 500, probably 'not implemented' - pass - if user: - resp = self.shortcmd('authinfo user '+user) - if resp[:3] == '381': - if not password: - raise NNTPReplyError(resp) - else: - resp = self.shortcmd( - 'authinfo pass '+password) - if resp[:3] != '281': - raise NNTPPermanentError(resp) + readermode is sometimes necessary if you are connecting to an + NNTP server on the local machine and intend to call + reader-specific comamnds, such as `group'. If you get + unexpected NNTPPermanentErrors, you might need to set + readermode. + """ + self.host = host + self.port = port + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect((self.host, self.port)) + self.file = self.sock.makefile('rb') + self.debugging = 0 + self.welcome = self.getresp() + if readermode: + try: + self.welcome = self.shortcmd('mode reader') + except NNTPPermanentError: + # error 500, probably 'not implemented' + pass + if user: + resp = self.shortcmd('authinfo user '+user) + if resp[:3] == '381': + if not password: + raise NNTPReplyError(resp) + else: + resp = self.shortcmd( + 'authinfo pass '+password) + if resp[:3] != '281': + raise NNTPPermanentError(resp) - # Get the welcome message from the server - # (this is read and squirreled away by __init__()). - # If the response code is 200, posting is allowed; - # if it 201, posting is not allowed + # Get the welcome message from the server + # (this is read and squirreled away by __init__()). + # If the response code is 200, posting is allowed; + # if it 201, posting is not allowed - def getwelcome(self): - """Get the welcome message from the server - (this is read and squirreled away by __init__()). - If the response code is 200, posting is allowed; - if it 201, posting is not allowed.""" + def getwelcome(self): + """Get the welcome message from the server + (this is read and squirreled away by __init__()). + If the response code is 200, posting is allowed; + if it 201, posting is not allowed.""" - if self.debugging: print '*welcome*', `self.welcome` - return self.welcome + if self.debugging: print '*welcome*', `self.welcome` + return self.welcome - def set_debuglevel(self, level): - """Set the debugging level. Argument 'level' means: - 0: no debugging output (default) - 1: print commands and responses but not body text etc. - 2: also print raw lines read and sent before stripping CR/LF""" + def set_debuglevel(self, level): + """Set the debugging level. Argument 'level' means: + 0: no debugging output (default) + 1: print commands and responses but not body text etc. + 2: also print raw lines read and sent before stripping CR/LF""" - self.debugging = level - debug = set_debuglevel + self.debugging = level + debug = set_debuglevel - def putline(self, line): - """Internal: send one line to the server, appending CRLF.""" - line = line + CRLF - if self.debugging > 1: print '*put*', `line` - self.sock.send(line) + def putline(self, line): + """Internal: send one line to the server, appending CRLF.""" + line = line + CRLF + if self.debugging > 1: print '*put*', `line` + self.sock.send(line) - def putcmd(self, line): - """Internal: send one command to the server (through putline()).""" - if self.debugging: print '*cmd*', `line` - self.putline(line) + def putcmd(self, line): + """Internal: send one command to the server (through putline()).""" + if self.debugging: print '*cmd*', `line` + self.putline(line) - def getline(self): - """Internal: return one line from the server, stripping CRLF. - Raise EOFError if the connection is closed.""" - line = self.file.readline() - if self.debugging > 1: - print '*get*', `line` - if not line: raise EOFError - if line[-2:] == CRLF: line = line[:-2] - elif line[-1:] in CRLF: line = line[:-1] - return line + def getline(self): + """Internal: return one line from the server, stripping CRLF. + Raise EOFError if the connection is closed.""" + line = self.file.readline() + if self.debugging > 1: + print '*get*', `line` + if not line: raise EOFError + if line[-2:] == CRLF: line = line[:-2] + elif line[-1:] in CRLF: line = line[:-1] + return line - def getresp(self): - """Internal: get a response from the server. - Raise various errors if the response indicates an error.""" - resp = self.getline() - if self.debugging: print '*resp*', `resp` - c = resp[:1] - if c == '4': - raise NNTPTemporaryError(resp) - if c == '5': - raise NNTPPermanentError(resp) - if c not in '123': - raise NNTPProtocolError(resp) - return resp + def getresp(self): + """Internal: get a response from the server. + Raise various errors if the response indicates an error.""" + resp = self.getline() + if self.debugging: print '*resp*', `resp` + c = resp[:1] + if c == '4': + raise NNTPTemporaryError(resp) + if c == '5': + raise NNTPPermanentError(resp) + if c not in '123': + raise NNTPProtocolError(resp) + return resp - def getlongresp(self): - """Internal: get a response plus following text from the server. - Raise various errors if the response indicates an error.""" - resp = self.getresp() - if resp[:3] not in LONGRESP: - raise NNTPReplyError(resp) - list = [] - while 1: - line = self.getline() - if line == '.': - break - if line[:2] == '..': - line = line[1:] - list.append(line) - return resp, list + def getlongresp(self): + """Internal: get a response plus following text from the server. + Raise various errors if the response indicates an error.""" + resp = self.getresp() + if resp[:3] not in LONGRESP: + raise NNTPReplyError(resp) + list = [] + while 1: + line = self.getline() + if line == '.': + break + if line[:2] == '..': + line = line[1:] + list.append(line) + return resp, list - def shortcmd(self, line): - """Internal: send a command and get the response.""" - self.putcmd(line) - return self.getresp() + def shortcmd(self, line): + """Internal: send a command and get the response.""" + self.putcmd(line) + return self.getresp() - def longcmd(self, line): - """Internal: send a command and get the response plus following text.""" - self.putcmd(line) - return self.getlongresp() + def longcmd(self, line): + """Internal: send a command and get the response plus following text.""" + self.putcmd(line) + return self.getlongresp() - def newgroups(self, date, time): - """Process a NEWGROUPS command. Arguments: - - date: string 'yymmdd' indicating the date - - time: string 'hhmmss' indicating the time - Return: - - resp: server response if successful - - list: list of newsgroup names""" + def newgroups(self, date, time): + """Process a NEWGROUPS command. Arguments: + - date: string 'yymmdd' indicating the date + - time: string 'hhmmss' indicating the time + Return: + - resp: server response if successful + - list: list of newsgroup names""" - return self.longcmd('NEWGROUPS ' + date + ' ' + time) + return self.longcmd('NEWGROUPS ' + date + ' ' + time) - def newnews(self, group, date, time): - """Process a NEWNEWS command. Arguments: - - group: group name or '*' - - date: string 'yymmdd' indicating the date - - time: string 'hhmmss' indicating the time - Return: - - resp: server response if successful - - list: list of article ids""" + def newnews(self, group, date, time): + """Process a NEWNEWS command. Arguments: + - group: group name or '*' + - date: string 'yymmdd' indicating the date + - time: string 'hhmmss' indicating the time + Return: + - resp: server response if successful + - list: list of article ids""" - cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time - return self.longcmd(cmd) + cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time + return self.longcmd(cmd) - def list(self): - """Process a LIST command. Return: - - resp: server response if successful - - list: list of (group, last, first, flag) (strings)""" + def list(self): + """Process a LIST command. Return: + - resp: server response if successful + - list: list of (group, last, first, flag) (strings)""" - resp, list = self.longcmd('LIST') - for i in range(len(list)): - # Parse lines into "group last first flag" - list[i] = tuple(string.split(list[i])) - return resp, list + resp, list = self.longcmd('LIST') + for i in range(len(list)): + # Parse lines into "group last first flag" + list[i] = tuple(string.split(list[i])) + return resp, list - def group(self, name): - """Process a GROUP command. Argument: - - group: the group name - Returns: - - resp: server response if successful - - count: number of articles (string) - - first: first article number (string) - - last: last article number (string) - - name: the group name""" + def group(self, name): + """Process a GROUP command. Argument: + - group: the group name + Returns: + - resp: server response if successful + - count: number of articles (string) + - first: first article number (string) + - last: last article number (string) + - name: the group name""" - resp = self.shortcmd('GROUP ' + name) - if resp[:3] != '211': - raise NNTPReplyError(resp) - words = string.split(resp) - count = first = last = 0 - n = len(words) - if n > 1: - count = words[1] - if n > 2: - first = words[2] - if n > 3: - last = words[3] - if n > 4: - name = string.lower(words[4]) - return resp, count, first, last, name + resp = self.shortcmd('GROUP ' + name) + if resp[:3] != '211': + raise NNTPReplyError(resp) + words = string.split(resp) + count = first = last = 0 + n = len(words) + if n > 1: + count = words[1] + if n > 2: + first = words[2] + if n > 3: + last = words[3] + if n > 4: + name = string.lower(words[4]) + return resp, count, first, last, name - def help(self): - """Process a HELP command. Returns: - - resp: server response if successful - - list: list of strings""" + def help(self): + """Process a HELP command. Returns: + - resp: server response if successful + - list: list of strings""" - return self.longcmd('HELP') + return self.longcmd('HELP') - def statparse(self, resp): - """Internal: parse the response of a STAT, NEXT or LAST command.""" - if resp[:2] != '22': - raise NNTPReplyError(resp) - words = string.split(resp) - nr = 0 - id = '' - n = len(words) - if n > 1: - nr = words[1] - if n > 2: - id = words[2] - return resp, nr, id + def statparse(self, resp): + """Internal: parse the response of a STAT, NEXT or LAST command.""" + if resp[:2] != '22': + raise NNTPReplyError(resp) + words = string.split(resp) + nr = 0 + id = '' + n = len(words) + if n > 1: + nr = words[1] + if n > 2: + id = words[2] + return resp, nr, id - def statcmd(self, line): - """Internal: process a STAT, NEXT or LAST command.""" - resp = self.shortcmd(line) - return self.statparse(resp) + def statcmd(self, line): + """Internal: process a STAT, NEXT or LAST command.""" + resp = self.shortcmd(line) + return self.statparse(resp) - def stat(self, id): - """Process a STAT command. Argument: - - id: article number or message id - Returns: - - resp: server response if successful - - nr: the article number - - id: the article id""" + def stat(self, id): + """Process a STAT command. Argument: + - id: article number or message id + Returns: + - resp: server response if successful + - nr: the article number + - id: the article id""" - return self.statcmd('STAT ' + id) + return self.statcmd('STAT ' + id) - def next(self): - """Process a NEXT command. No arguments. Return as for STAT.""" - return self.statcmd('NEXT') + def next(self): + """Process a NEXT command. No arguments. Return as for STAT.""" + return self.statcmd('NEXT') - def last(self): - """Process a LAST command. No arguments. Return as for STAT.""" - return self.statcmd('LAST') + def last(self): + """Process a LAST command. No arguments. Return as for STAT.""" + return self.statcmd('LAST') - def artcmd(self, line): - """Internal: process a HEAD, BODY or ARTICLE command.""" - resp, list = self.longcmd(line) - resp, nr, id = self.statparse(resp) - return resp, nr, id, list + def artcmd(self, line): + """Internal: process a HEAD, BODY or ARTICLE command.""" + resp, list = self.longcmd(line) + resp, nr, id = self.statparse(resp) + return resp, nr, id, list - def head(self, id): - """Process a HEAD command. Argument: - - id: article number or message id - Returns: - - resp: server response if successful - - nr: article number - - id: message id - - list: the lines of the article's header""" + def head(self, id): + """Process a HEAD command. Argument: + - id: article number or message id + Returns: + - resp: server response if successful + - nr: article number + - id: message id + - list: the lines of the article's header""" - return self.artcmd('HEAD ' + id) + return self.artcmd('HEAD ' + id) - def body(self, id): - """Process a BODY command. Argument: - - id: article number or message id - Returns: - - resp: server response if successful - - nr: article number - - id: message id - - list: the lines of the article's body""" + def body(self, id): + """Process a BODY command. Argument: + - id: article number or message id + Returns: + - resp: server response if successful + - nr: article number + - id: message id + - list: the lines of the article's body""" - return self.artcmd('BODY ' + id) + return self.artcmd('BODY ' + id) - def article(self, id): - """Process an ARTICLE command. Argument: - - id: article number or message id - Returns: - - resp: server response if successful - - nr: article number - - id: message id - - list: the lines of the article""" + def article(self, id): + """Process an ARTICLE command. Argument: + - id: article number or message id + Returns: + - resp: server response if successful + - nr: article number + - id: message id + - list: the lines of the article""" - return self.artcmd('ARTICLE ' + id) + return self.artcmd('ARTICLE ' + id) - def slave(self): - """Process a SLAVE command. Returns: - - resp: server response if successful""" + def slave(self): + """Process a SLAVE command. Returns: + - resp: server response if successful""" - return self.shortcmd('SLAVE') + return self.shortcmd('SLAVE') - def xhdr(self, hdr, str): - """Process an XHDR command (optional server extension). Arguments: - - hdr: the header type (e.g. 'subject') - - str: an article nr, a message id, or a range nr1-nr2 - Returns: - - resp: server response if successful - - list: list of (nr, value) strings""" + def xhdr(self, hdr, str): + """Process an XHDR command (optional server extension). Arguments: + - hdr: the header type (e.g. 'subject') + - str: an article nr, a message id, or a range nr1-nr2 + Returns: + - resp: server response if successful + - list: list of (nr, value) strings""" - pat = re.compile('^([0-9]+) ?(.*)\n?') - resp, lines = self.longcmd('XHDR ' + hdr + ' ' + str) - for i in range(len(lines)): - line = lines[i] - m = pat.match(line) - if m: - lines[i] = m.group(1, 2) - return resp, lines + pat = re.compile('^([0-9]+) ?(.*)\n?') + resp, lines = self.longcmd('XHDR ' + hdr + ' ' + str) + for i in range(len(lines)): + line = lines[i] + m = pat.match(line) + if m: + lines[i] = m.group(1, 2) + return resp, lines - def xover(self,start,end): - """Process an XOVER command (optional server extension) Arguments: - - start: start of range - - end: end of range - Returns: - - resp: server response if successful - - list: list of (art-nr, subject, poster, date, - id, references, size, lines)""" + def xover(self,start,end): + """Process an XOVER command (optional server extension) Arguments: + - start: start of range + - end: end of range + Returns: + - resp: server response if successful + - list: list of (art-nr, subject, poster, date, + id, references, size, lines)""" - resp, lines = self.longcmd('XOVER ' + start + '-' + end) - xover_lines = [] - for line in lines: - elem = string.splitfields(line,"\t") - try: - xover_lines.append((elem[0], - elem[1], - elem[2], - elem[3], - elem[4], - string.split(elem[5]), - elem[6], - elem[7])) - except IndexError: - raise NNTPDataError(line) - return resp,xover_lines + resp, lines = self.longcmd('XOVER ' + start + '-' + end) + xover_lines = [] + for line in lines: + elem = string.splitfields(line,"\t") + try: + xover_lines.append((elem[0], + elem[1], + elem[2], + elem[3], + elem[4], + string.split(elem[5]), + elem[6], + elem[7])) + except IndexError: + raise NNTPDataError(line) + return resp,xover_lines - def xgtitle(self, group): - """Process an XGTITLE command (optional server extension) Arguments: - - group: group name wildcard (i.e. news.*) - Returns: - - resp: server response if successful - - list: list of (name,title) strings""" + def xgtitle(self, group): + """Process an XGTITLE command (optional server extension) Arguments: + - group: group name wildcard (i.e. news.*) + Returns: + - resp: server response if successful + - list: list of (name,title) strings""" - line_pat = re.compile("^([^ \t]+)[ \t]+(.*)$") - resp, raw_lines = self.longcmd('XGTITLE ' + group) - lines = [] - for raw_line in raw_lines: - match = line_pat.search(string.strip(raw_line)) - if match: - lines.append(match.group(1, 2)) - return resp, lines + line_pat = re.compile("^([^ \t]+)[ \t]+(.*)$") + resp, raw_lines = self.longcmd('XGTITLE ' + group) + lines = [] + for raw_line in raw_lines: + match = line_pat.search(string.strip(raw_line)) + if match: + lines.append(match.group(1, 2)) + return resp, lines - def xpath(self,id): - """Process an XPATH command (optional server extension) Arguments: - - id: Message id of article - Returns: - resp: server response if successful - path: directory path to article""" + def xpath(self,id): + """Process an XPATH command (optional server extension) Arguments: + - id: Message id of article + Returns: + resp: server response if successful + path: directory path to article""" - resp = self.shortcmd("XPATH " + id) - if resp[:3] != '223': - raise NNTPReplyError(resp) - try: - [resp_num, path] = string.split(resp) - except ValueError: - raise NNTPReplyError(resp) - else: - return resp, path + resp = self.shortcmd("XPATH " + id) + if resp[:3] != '223': + raise NNTPReplyError(resp) + try: + [resp_num, path] = string.split(resp) + except ValueError: + raise NNTPReplyError(resp) + else: + return resp, path - def date (self): - """Process the DATE command. Arguments: - None - Returns: - resp: server response if successful - date: Date suitable for newnews/newgroups commands etc. - time: Time suitable for newnews/newgroups commands etc.""" + def date (self): + """Process the DATE command. Arguments: + None + Returns: + resp: server response if successful + date: Date suitable for newnews/newgroups commands etc. + time: Time suitable for newnews/newgroups commands etc.""" - resp = self.shortcmd("DATE") - if resp[:3] != '111': - raise NNTPReplyError(resp) - elem = string.split(resp) - if len(elem) != 2: - raise NNTPDataError(resp) - date = elem[1][2:8] - time = elem[1][-6:] - if len(date) != 6 or len(time) != 6: - raise NNTPDataError(resp) - return resp, date, time + resp = self.shortcmd("DATE") + if resp[:3] != '111': + raise NNTPReplyError(resp) + elem = string.split(resp) + if len(elem) != 2: + raise NNTPDataError(resp) + date = elem[1][2:8] + time = elem[1][-6:] + if len(date) != 6 or len(time) != 6: + raise NNTPDataError(resp) + return resp, date, time - def post(self, f): - """Process a POST command. Arguments: - - f: file containing the article - Returns: - - resp: server response if successful""" + def post(self, f): + """Process a POST command. Arguments: + - f: file containing the article + Returns: + - resp: server response if successful""" - resp = self.shortcmd('POST') - # Raises error_??? if posting is not allowed - if resp[0] != '3': - raise NNTPReplyError(resp) - while 1: - line = f.readline() - if not line: - break - if line[-1] == '\n': - line = line[:-1] - if line[:1] == '.': - line = '.' + line - self.putline(line) - self.putline('.') - return self.getresp() + resp = self.shortcmd('POST') + # Raises error_??? if posting is not allowed + if resp[0] != '3': + raise NNTPReplyError(resp) + while 1: + line = f.readline() + if not line: + break + if line[-1] == '\n': + line = line[:-1] + if line[:1] == '.': + line = '.' + line + self.putline(line) + self.putline('.') + return self.getresp() - def ihave(self, id, f): - """Process an IHAVE command. Arguments: - - id: message-id of the article - - f: file containing the article - Returns: - - resp: server response if successful - Note that if the server refuses the article an exception is raised.""" + def ihave(self, id, f): + """Process an IHAVE command. Arguments: + - id: message-id of the article + - f: file containing the article + Returns: + - resp: server response if successful + Note that if the server refuses the article an exception is raised.""" - resp = self.shortcmd('IHAVE ' + id) - # Raises error_??? if the server already has it - if resp[0] != '3': - raise NNTPReplyError(resp) - while 1: - line = f.readline() - if not line: - break - if line[-1] == '\n': - line = line[:-1] - if line[:1] == '.': - line = '.' + line - self.putline(line) - self.putline('.') - return self.getresp() + resp = self.shortcmd('IHAVE ' + id) + # Raises error_??? if the server already has it + if resp[0] != '3': + raise NNTPReplyError(resp) + while 1: + line = f.readline() + if not line: + break + if line[-1] == '\n': + line = line[:-1] + if line[:1] == '.': + line = '.' + line + self.putline(line) + self.putline('.') + return self.getresp() - def quit(self): - """Process a QUIT command and close the socket. Returns: - - resp: server response if successful""" + def quit(self): + """Process a QUIT command and close the socket. Returns: + - resp: server response if successful""" - resp = self.shortcmd('QUIT') - self.file.close() - self.sock.close() - del self.file, self.sock - return resp + resp = self.shortcmd('QUIT') + self.file.close() + self.sock.close() + del self.file, self.sock + return resp def _test(): - """Minimal test function.""" - s = NNTP('news', readermode='reader') - resp, count, first, last, name = s.group('comp.lang.python') - print resp - print 'Group', name, 'has', count, 'articles, range', first, 'to', last - resp, subs = s.xhdr('subject', first + '-' + last) - print resp - for item in subs: - print "%7s %s" % item - resp = s.quit() - print resp + """Minimal test function.""" + s = NNTP('news', readermode='reader') + resp, count, first, last, name = s.group('comp.lang.python') + print resp + print 'Group', name, 'has', count, 'articles, range', first, 'to', last + resp, subs = s.xhdr('subject', first + '-' + last) + print resp + for item in subs: + print "%7s %s" % item + resp = s.quit() + print resp # Run the test when run as a script if __name__ == '__main__': - _test() + _test() diff --git a/Lib/ntpath.py b/Lib/ntpath.py index c1f4df7d4c8..571a7d0dd85 100644 --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -1,5 +1,5 @@ # Module 'ntpath' -- common operations on WinNT/Win95 pathnames -"""Common pathname manipulations, WindowsNT/95 version. +"""Common pathname manipulations, WindowsNT/95 version. Instead of importing this module directly, import os and refer to this module as os.path. @@ -254,7 +254,7 @@ def ismount(path): def walk(top, func, arg): """Directory tree walk whth callback function. - walk(top, func, arg) calls func(arg, d, files) for each directory d + walk(top, func, arg) calls func(arg, d, files) for each directory d in the tree rooted at top (including top itself); files is a list of all the files and subdirs in directory d.""" try: @@ -313,7 +313,7 @@ def expanduser(path): # XXX With COMMAND.COM you can use any characters in a variable name, # XXX except '^|<>='. -def expandvars(path): +def expandvars(path): """Expand shell variables of form $var and ${var}. Unknown variables are left unchanged.""" diff --git a/Lib/nturl2path.py b/Lib/nturl2path.py index 0445b8afb0f..2d08eee1b0e 100644 --- a/Lib/nturl2path.py +++ b/Lib/nturl2path.py @@ -1,66 +1,66 @@ """Convert a NT pathname to a file URL and vice versa.""" def url2pathname(url): - r"""Convert a URL to a DOS path. + r"""Convert a URL to a DOS path. - ///C|/foo/bar/spam.foo + ///C|/foo/bar/spam.foo - becomes + becomes - C:\foo\bar\spam.foo - """ - import string, urllib - if not '|' in url: - # No drive specifier, just convert slashes - if url[:4] == '////': - # path is something like ////host/path/on/remote/host - # convert this to \\host\path\on\remote\host - # (notice halving of slashes at the start of the path) - url = url[2:] - components = string.split(url, '/') - # make sure not to convert quoted slashes :-) - return urllib.unquote(string.join(components, '\\')) - comp = string.split(url, '|') - if len(comp) != 2 or comp[0][-1] not in string.letters: - error = 'Bad URL: ' + url - raise IOError, error - drive = string.upper(comp[0][-1]) - components = string.split(comp[1], '/') - path = drive + ':' - for comp in components: - if comp: - path = path + '\\' + urllib.unquote(comp) - return path + C:\foo\bar\spam.foo + """ + import string, urllib + if not '|' in url: + # No drive specifier, just convert slashes + if url[:4] == '////': + # path is something like ////host/path/on/remote/host + # convert this to \\host\path\on\remote\host + # (notice halving of slashes at the start of the path) + url = url[2:] + components = string.split(url, '/') + # make sure not to convert quoted slashes :-) + return urllib.unquote(string.join(components, '\\')) + comp = string.split(url, '|') + if len(comp) != 2 or comp[0][-1] not in string.letters: + error = 'Bad URL: ' + url + raise IOError, error + drive = string.upper(comp[0][-1]) + components = string.split(comp[1], '/') + path = drive + ':' + for comp in components: + if comp: + path = path + '\\' + urllib.unquote(comp) + return path def pathname2url(p): - r"""Convert a DOS path name to a file url. + r"""Convert a DOS path name to a file url. - C:\foo\bar\spam.foo + C:\foo\bar\spam.foo - becomes + becomes - ///C|/foo/bar/spam.foo - """ + ///C|/foo/bar/spam.foo + """ - import string, urllib - if not ':' in p: - # No drive specifier, just convert slashes and quote the name - if p[:2] == '\\\\': - # path is something like \\host\path\on\remote\host - # convert this to ////host/path/on/remote/host - # (notice doubling of slashes at the start of the path) - p = '\\\\' + p - components = string.split(p, '\\') - return urllib.quote(string.join(components, '/')) - comp = string.split(p, ':') - if len(comp) != 2 or len(comp[0]) > 1: - error = 'Bad path: ' + p - raise IOError, error + import string, urllib + if not ':' in p: + # No drive specifier, just convert slashes and quote the name + if p[:2] == '\\\\': + # path is something like \\host\path\on\remote\host + # convert this to ////host/path/on/remote/host + # (notice doubling of slashes at the start of the path) + p = '\\\\' + p + components = string.split(p, '\\') + return urllib.quote(string.join(components, '/')) + comp = string.split(p, ':') + if len(comp) != 2 or len(comp[0]) > 1: + error = 'Bad path: ' + p + raise IOError, error - drive = urllib.quote(string.upper(comp[0])) - components = string.split(comp[1], '\\') - path = '///' + drive + '|' - for comp in components: - if comp: - path = path + '/' + urllib.quote(comp) - return path + drive = urllib.quote(string.upper(comp[0])) + components = string.split(comp[1], '\\') + path = '///' + drive + '|' + for comp in components: + if comp: + path = path + '/' + urllib.quote(comp) + return path diff --git a/Lib/os.py b/Lib/os.py index ea380212db7..0ccdad2662a 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -213,7 +213,7 @@ def execlpe(file, *args): Execute the executable file (which is searched for along $PATH) with argument list args and environment env, replacing the current - process. """ + process. """ env = args[-1] execvpe(file, args[:-1], env) @@ -231,7 +231,7 @@ def execvpe(file, args, env): Execute the executable file (which is searched for along $PATH) with argument list args and environment env , replacing the current process. - args may be a list or tuple of strings. """ + args may be a list or tuple of strings. """ _execvpe(file, args, env) _notfound = None @@ -370,7 +370,7 @@ if _exists("fork") and not _exists("spawnv") and _exists("execv"): Execute file with arguments from args in a subprocess. If mode == P_NOWAIT return the pid of the process. If mode == P_WAIT return the process's exit code if it exits normally; -otherwise return -SIG, where SIG is the signal that killed it. """ +otherwise return -SIG, where SIG is the signal that killed it. """ return _spawnvef(mode, file, args, None, execv) def spawnve(mode, file, args, env): diff --git a/Lib/pdb.py b/Lib/pdb.py index 697fb88d3c0..cb1a4d2348f 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -14,893 +14,893 @@ import os import re def find_function(funcname, filename): - cre = re.compile(r'def\s+%s\s*[(]' % funcname) - try: - fp = open(filename) - except IOError: - return None - # consumer of this info expects the first line to be 1 - lineno = 1 - answer = None - while 1: - line = fp.readline() - if line == '': - break - if cre.match(line): - answer = funcname, filename, lineno - break - lineno = lineno + 1 - fp.close() - return answer + cre = re.compile(r'def\s+%s\s*[(]' % funcname) + try: + fp = open(filename) + except IOError: + return None + # consumer of this info expects the first line to be 1 + lineno = 1 + answer = None + while 1: + line = fp.readline() + if line == '': + break + if cre.match(line): + answer = funcname, filename, lineno + break + lineno = lineno + 1 + fp.close() + return answer # Interaction prompt line will separate file and call info from code # text using value of line_prefix string. A newline and arrow may # be to your liking. You can set it once pdb is imported using the # command "pdb.line_prefix = '\n% '". -# line_prefix = ': ' # Use this to get the old situation back -line_prefix = '\n-> ' # Probably a better default +# line_prefix = ': ' # Use this to get the old situation back +line_prefix = '\n-> ' # Probably a better default class Pdb(bdb.Bdb, cmd.Cmd): - - def __init__(self): - bdb.Bdb.__init__(self) - cmd.Cmd.__init__(self) - self.prompt = '(Pdb) ' - self.aliases = {} - # Try to load readline if it exists - try: - import readline - except ImportError: - pass - - # Read $HOME/.pdbrc and ./.pdbrc - self.rcLines = [] - if os.environ.has_key('HOME'): - envHome = os.environ['HOME'] - try: - rcFile = open(os.path.join(envHome, ".pdbrc")) - except IOError: - pass - else: - for line in rcFile.readlines(): - self.rcLines.append(line) - rcFile.close() - try: - rcFile = open(".pdbrc") - except IOError: - pass - else: - for line in rcFile.readlines(): - self.rcLines.append(line) - rcFile.close() - - def reset(self): - bdb.Bdb.reset(self) - self.forget() - - def forget(self): - self.lineno = None - self.stack = [] - self.curindex = 0 - self.curframe = None - - def setup(self, f, t): - self.forget() - self.stack, self.curindex = self.get_stack(f, t) - self.curframe = self.stack[self.curindex][0] - self.execRcLines() - - # Can be executed earlier than 'setup' if desired - def execRcLines(self): - if self.rcLines: - # Make local copy because of recursion - rcLines = self.rcLines - # executed only once - self.rcLines = [] - for line in rcLines: - line = line[:-1] - if len (line) > 0 and line[0] != '#': - self.onecmd (line) - - # Override Bdb methods (except user_call, for now) - - def user_line(self, frame): - """This function is called when we stop or break at this line.""" - self.interaction(frame, None) - - def user_return(self, frame, return_value): - """This function is called when a return trap is set here.""" - frame.f_locals['__return__'] = return_value - print '--Return--' - self.interaction(frame, None) - - def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): - """This function is called if an exception occurs, - but only if we are to stop at or just below this level.""" - frame.f_locals['__exception__'] = exc_type, exc_value - if type(exc_type) == type(''): - exc_type_name = exc_type - else: exc_type_name = exc_type.__name__ - print exc_type_name + ':', repr.repr(exc_value) - self.interaction(frame, exc_traceback) - - # General interaction function - - def interaction(self, frame, traceback): - self.setup(frame, traceback) - self.print_stack_entry(self.stack[self.curindex]) - self.cmdloop() - self.forget() - - def default(self, line): - if line[:1] == '!': line = line[1:] - locals = self.curframe.f_locals - globals = self.curframe.f_globals - try: - code = compile(line + '\n', '', 'single') - exec code in globals, locals - except: - t, v = sys.exc_info()[:2] - if type(t) == type(''): - exc_type_name = t - else: exc_type_name = t.__name__ - print '***', exc_type_name + ':', v - - def precmd(self, line): - """Handle alias expansion and ';;' separator.""" - if not line: - return line - args = string.split(line) - while self.aliases.has_key(args[0]): - line = self.aliases[args[0]] - ii = 1 - for tmpArg in args[1:]: - line = string.replace(line, "%" + str(ii), - tmpArg) - ii = ii + 1 - line = string.replace(line, "%*", - string.join(args[1:], ' ')) - args = string.split(line) - # split into ';;' separated commands - # unless it's an alias command - if args[0] != 'alias': - marker = string.find(line, ';;') - if marker >= 0: - # queue up everything after marker - next = string.lstrip(line[marker+2:]) - self.cmdqueue.append(next) - line = string.rstrip(line[:marker]) - return line - - # Command definitions, called by cmdloop() - # The argument is the remaining string on the command line - # Return true to exit from the command loop - - do_h = cmd.Cmd.do_help - - def do_EOF(self, arg): - return 0 # Don't die on EOF - - def do_break(self, arg, temporary = 0): - # break [ ([filename:]lineno | function) [, "condition"] ] - if not arg: - if self.breaks: # There's at least one - print "Num Type Disp Enb Where" - for bp in bdb.Breakpoint.bpbynumber: - if bp: - bp.bpprint() - return - # parse arguments; comma has lowest precedence - # and cannot occur in filename - filename = None - lineno = None - cond = None - comma = string.find(arg, ',') - if comma > 0: - # parse stuff after comma: "condition" - cond = string.lstrip(arg[comma+1:]) - arg = string.rstrip(arg[:comma]) - # parse stuff before comma: [filename:]lineno | function - colon = string.rfind(arg, ':') - if colon >= 0: - filename = string.rstrip(arg[:colon]) - f = self.lookupmodule(filename) - if not f: - print '*** ', `filename`, - print 'not found from sys.path' - return - else: - filename = f - arg = string.lstrip(arg[colon+1:]) - try: - lineno = int(arg) - except ValueError, msg: - print '*** Bad lineno:', arg - return - else: - # no colon; can be lineno or function - try: - lineno = int(arg) - except ValueError: - try: - func = eval(arg, - self.curframe.f_globals, - self.curframe.f_locals) - except: - func = arg - try: - if hasattr(func, 'im_func'): - func = func.im_func - code = func.func_code - lineno = code.co_firstlineno - filename = code.co_filename - except: - # last thing to try - (ok, filename, ln) = self.lineinfo(arg) - if not ok: - print '*** The specified object', - print `arg`, - print 'is not a function' - print ('or was not found ' - 'along sys.path.') - return - lineno = int(ln) - if not filename: - filename = self.defaultFile() - # Check for reasonable breakpoint - line = self.checkline(filename, lineno) - if line: - # now set the break point - err = self.set_break(filename, line, temporary, cond) - if err: print '***', err - else: - bp = self.get_breaks(filename, line)[-1] - print "Breakpoint %d at %s:%d" % (bp.number, - bp.file, - bp.line) - - # To be overridden in derived debuggers - def defaultFile(self): - """Produce a reasonable default.""" - filename = self.curframe.f_code.co_filename - if filename == '' and mainpyfile: - filename = mainpyfile - return filename - - do_b = do_break - - def do_tbreak(self, arg): - self.do_break(arg, 1) - - def lineinfo(self, identifier): - failed = (None, None, None) - # Input is identifier, may be in single quotes - idstring = string.split(identifier, "'") - if len(idstring) == 1: - # not in single quotes - id = string.strip(idstring[0]) - elif len(idstring) == 3: - # quoted - id = string.strip(idstring[1]) - else: - return failed - if id == '': return failed - parts = string.split(id, '.') - # Protection for derived debuggers - if parts[0] == 'self': - del parts[0] - if len(parts) == 0: - return failed - # Best first guess at file to look at - fname = self.defaultFile() - if len(parts) == 1: - item = parts[0] - else: - # More than one part. - # First is module, second is method/class - f = self.lookupmodule(parts[0]) - if f: - fname = f - item = parts[1] - answer = find_function(item, fname) - return answer or failed - - def checkline(self, filename, lineno): - """Return line number of first line at or after input - argument such that if the input points to a 'def', the - returned line number is the first - non-blank/non-comment line to follow. If the input - points to a blank or comment line, return 0. At end - of file, also return 0.""" - - line = linecache.getline(filename, lineno) - if not line: - print 'End of file' - return 0 - line = string.strip(line) - # Don't allow setting breakpoint at a blank line - if ( not line or (line[0] == '#') or - (line[:3] == '"""') or line[:3] == "'''" ): - print '*** Blank or comment' - return 0 - # When a file is read in and a breakpoint is at - # the 'def' statement, the system stops there at - # code parse time. We don't want that, so all breakpoints - # set at 'def' statements are moved one line onward - if line[:3] == 'def': - instr = '' - brackets = 0 - while 1: - skipone = 0 - for c in line: - if instr: - if skipone: - skipone = 0 - elif c == '\\': - skipone = 1 - elif c == instr: - instr = '' - elif c == '#': - break - elif c in ('"',"'"): - instr = c - elif c in ('(','{','['): - brackets = brackets + 1 - elif c in (')','}',']'): - brackets = brackets - 1 - lineno = lineno+1 - line = linecache.getline(filename, lineno) - if not line: - print 'end of file' - return 0 - line = string.strip(line) - if not line: continue # Blank line - if brackets <= 0 and line[0] not in ('#','"',"'"): - break - return lineno - - def do_enable(self, arg): - args = string.split(arg) - for i in args: - bp = bdb.Breakpoint.bpbynumber[int(i)] - if bp: - bp.enable() - - def do_disable(self, arg): - args = string.split(arg) - for i in args: - bp = bdb.Breakpoint.bpbynumber[int(i)] - if bp: - bp.disable() - - def do_condition(self, arg): - # arg is breakpoint number and condition - args = string.split(arg, ' ', 1) - bpnum = int(string.strip(args[0])) - try: - cond = args[1] - except: - cond = None - bp = bdb.Breakpoint.bpbynumber[bpnum] - if bp: - bp.cond = cond - if not cond: - print 'Breakpoint', bpnum, - print 'is now unconditional.' - - def do_ignore(self,arg): - """arg is bp number followed by ignore count.""" - args = string.split(arg) - bpnum = int(string.strip(args[0])) - try: - count = int(string.strip(args[1])) - except: - count = 0 - bp = bdb.Breakpoint.bpbynumber[bpnum] - if bp: - bp.ignore = count - if (count > 0): - reply = 'Will ignore next ' - if (count > 1): - reply = reply + '%d crossings' % count - else: - reply = reply + '1 crossing' - print reply + ' of breakpoint %d.' % bpnum - else: - print 'Will stop next time breakpoint', - print bpnum, 'is reached.' - - def do_clear(self, arg): - """Three possibilities, tried in this order: - clear -> clear all breaks, ask for confirmation - clear file:lineno -> clear all breaks at file:lineno - clear bpno bpno ... -> clear breakpoints by number""" - if not arg: - try: - reply = raw_input('Clear all breaks? ') - except EOFError: - reply = 'no' - reply = string.lower(string.strip(reply)) - if reply in ('y', 'yes'): - self.clear_all_breaks() - return - if ':' in arg: - # Make sure it works for "clear C:\foo\bar.py:12" - i = string.rfind(arg, ':') - filename = arg[:i] - arg = arg[i+1:] - try: - lineno = int(arg) - except: - err = "Invalid line number (%s)" % arg - else: - err = self.clear_break(filename, lineno) - if err: print '***', err - return - numberlist = string.split(arg) - for i in numberlist: - err = self.clear_bpbynumber(i) - if err: - print '***', err - else: - print 'Deleted breakpoint %s ' % (i,) - do_cl = do_clear # 'c' is already an abbreviation for 'continue' - - def do_where(self, arg): - self.print_stack_trace() - do_w = do_where - - def do_up(self, arg): - if self.curindex == 0: - print '*** Oldest frame' - else: - self.curindex = self.curindex - 1 - self.curframe = self.stack[self.curindex][0] - self.print_stack_entry(self.stack[self.curindex]) - self.lineno = None - do_u = do_up - - def do_down(self, arg): - if self.curindex + 1 == len(self.stack): - print '*** Newest frame' - else: - self.curindex = self.curindex + 1 - self.curframe = self.stack[self.curindex][0] - self.print_stack_entry(self.stack[self.curindex]) - self.lineno = None - do_d = do_down - - def do_step(self, arg): - self.set_step() - return 1 - do_s = do_step - - def do_next(self, arg): - self.set_next(self.curframe) - return 1 - do_n = do_next - - def do_return(self, arg): - self.set_return(self.curframe) - return 1 - do_r = do_return - - def do_continue(self, arg): - self.set_continue() - return 1 - do_c = do_cont = do_continue - - def do_quit(self, arg): - self.set_quit() - return 1 - do_q = do_quit - - def do_args(self, arg): - f = self.curframe - co = f.f_code - dict = f.f_locals - n = co.co_argcount - if co.co_flags & 4: n = n+1 - if co.co_flags & 8: n = n+1 - for i in range(n): - name = co.co_varnames[i] - print name, '=', - if dict.has_key(name): print dict[name] - else: print "*** undefined ***" - do_a = do_args - - def do_retval(self, arg): - if self.curframe.f_locals.has_key('__return__'): - print self.curframe.f_locals['__return__'] - else: - print '*** Not yet returned!' - do_rv = do_retval - - def do_p(self, arg): - try: - value = eval(arg, self.curframe.f_globals, - self.curframe.f_locals) - except: - t, v = sys.exc_info()[:2] - if type(t) == type(''): - exc_type_name = t - else: exc_type_name = t.__name__ - print '***', exc_type_name + ':', `v` - return - - print `value` - - def do_list(self, arg): - self.lastcmd = 'list' - last = None - if arg: - try: - x = eval(arg, {}, {}) - if type(x) == type(()): - first, last = x - first = int(first) - last = int(last) - if last < first: - # Assume it's a count - last = first + last - else: - first = max(1, int(x) - 5) - except: - print '*** Error in argument:', `arg` - return - elif self.lineno is None: - first = max(1, self.curframe.f_lineno - 5) - else: - first = self.lineno + 1 - if last is None: - last = first + 10 - filename = self.curframe.f_code.co_filename - breaklist = self.get_file_breaks(filename) - try: - for lineno in range(first, last+1): - line = linecache.getline(filename, lineno) - if not line: - print '[EOF]' - break - else: - s = string.rjust(`lineno`, 3) - if len(s) < 4: s = s + ' ' - if lineno in breaklist: s = s + 'B' - else: s = s + ' ' - if lineno == self.curframe.f_lineno: - s = s + '->' - print s + '\t' + line, - self.lineno = lineno - except KeyboardInterrupt: - pass - do_l = do_list - - def do_whatis(self, arg): - try: - value = eval(arg, self.curframe.f_globals, - self.curframe.f_locals) - except: - t, v = sys.exc_info()[:2] - if type(t) == type(''): - exc_type_name = t - else: exc_type_name = t.__name__ - print '***', exc_type_name + ':', `v` - return - code = None - # Is it a function? - try: code = value.func_code - except: pass - if code: - print 'Function', code.co_name - return - # Is it an instance method? - try: code = value.im_func.func_code - except: pass - if code: - print 'Method', code.co_name - return - # None of the above... - print type(value) - - def do_alias(self, arg): - args = string.split (arg) - if len(args) == 0: - keys = self.aliases.keys() - keys.sort() - for alias in keys: - print "%s = %s" % (alias, self.aliases[alias]) - return - if self.aliases.has_key(args[0]) and len (args) == 1: - print "%s = %s" % (args[0], self.aliases[args[0]]) - else: - self.aliases[args[0]] = string.join(args[1:], ' ') - - def do_unalias(self, arg): - args = string.split (arg) - if len(args) == 0: return - if self.aliases.has_key(args[0]): - del self.aliases[args[0]] - - # Print a traceback starting at the top stack frame. - # The most recently entered frame is printed last; - # this is different from dbx and gdb, but consistent with - # the Python interpreter's stack trace. - # It is also consistent with the up/down commands (which are - # compatible with dbx and gdb: up moves towards 'main()' - # and down moves towards the most recent stack frame). - - def print_stack_trace(self): - try: - for frame_lineno in self.stack: - self.print_stack_entry(frame_lineno) - except KeyboardInterrupt: - pass - - def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix): - frame, lineno = frame_lineno - if frame is self.curframe: - print '>', - else: - print ' ', - print self.format_stack_entry(frame_lineno, prompt_prefix) - - - # Help methods (derived from pdb.doc) - - def help_help(self): - self.help_h() - - def help_h(self): - print """h(elp) - Without argument, print the list of available commands. - With a command name as argument, print help about that command - "help pdb" pipes the full documentation file to the $PAGER - "help exec" gives help on the ! command""" - - def help_where(self): - self.help_w() - - def help_w(self): - print """w(here) - Print a stack trace, with the most recent frame at the bottom. - An arrow indicates the "current frame", which determines the - context of most commands.""" - - def help_down(self): - self.help_d() - - def help_d(self): - print """d(own) - Move the current frame one level down in the stack trace - (to an older frame).""" - - def help_up(self): - self.help_u() - - def help_u(self): - print """u(p) - Move the current frame one level up in the stack trace - (to a newer frame).""" - - def help_break(self): - self.help_b() - - def help_b(self): - print """b(reak) ([file:]lineno | function) [, condition] - With a line number argument, set a break there in the current - file. With a function name, set a break at first executable line - of that function. Without argument, list all breaks. If a second - argument is present, it is a string specifying an expression - which must evaluate to true before the breakpoint is honored. - - The line number may be prefixed with a filename and a colon, - to specify a breakpoint in another file (probably one that - hasn't been loaded yet). The file is searched for on sys.path; - the .py suffix may be omitted.""" - - def help_clear(self): - self.help_cl() - - def help_cl(self): - print "cl(ear) filename:lineno" - print """cl(ear) [bpnumber [bpnumber...]] - With a space separated list of breakpoint numbers, clear - those breakpoints. Without argument, clear all breaks (but - first ask confirmation). With a filename:lineno argument, - clear all breaks at that line in that file. - - Note that the argument is different from previous versions of - the debugger (in python distributions 1.5.1 and before) where - a linenumber was used instead of either filename:lineno or - breakpoint numbers.""" - - def help_tbreak(self): - print """tbreak same arguments as break, but breakpoint is - removed when first hit.""" - - def help_enable(self): - print """enable bpnumber [bpnumber ...] - Enables the breakpoints given as a space separated list of - bp numbers.""" - - def help_disable(self): - print """disable bpnumber [bpnumber ...] - Disables the breakpoints given as a space separated list of - bp numbers.""" - - def help_ignore(self): - print """ignore bpnumber count - Sets the ignore count for the given breakpoint number. A breakpoint - becomes active when the ignore count is zero. When non-zero, the - count is decremented each time the breakpoint is reached and the - breakpoint is not disabled and any associated condition evaluates - to true.""" - - def help_condition(self): - print """condition bpnumber str_condition - str_condition is a string specifying an expression which - must evaluate to true before the breakpoint is honored. - If str_condition is absent, any existing condition is removed; - i.e., the breakpoint is made unconditional.""" - - def help_step(self): - self.help_s() - - def help_s(self): - print """s(tep) - Execute the current line, stop at the first possible occasion - (either in a function that is called or in the current function).""" - - def help_next(self): - self.help_n() - - def help_n(self): - print """n(ext) - Continue execution until the next line in the current function - is reached or it returns.""" - - def help_return(self): - self.help_r() - - def help_r(self): - print """r(eturn) - Continue execution until the current function returns.""" - - def help_continue(self): - self.help_c() - - def help_cont(self): - self.help_c() - - def help_c(self): - print """c(ont(inue)) - Continue execution, only stop when a breakpoint is encountered.""" - - def help_list(self): - self.help_l() - - def help_l(self): - print """l(ist) [first [,last]] - List source code for the current file. - Without arguments, list 11 lines around the current line - or continue the previous listing. - With one argument, list 11 lines starting at that line. - With two arguments, list the given range; - if the second argument is less than the first, it is a count.""" - - def help_args(self): - self.help_a() - - def help_a(self): - print """a(rgs) - Print the arguments of the current function.""" - - def help_p(self): - print """p expression - Print the value of the expression.""" - - def help_exec(self): - print """(!) statement - Execute the (one-line) statement in the context of - the current stack frame. - The exclamation point can be omitted unless the first word - of the statement resembles a debugger command. - To assign to a global variable you must always prefix the - command with a 'global' command, e.g.: - (Pdb) global list_options; list_options = ['-l'] - (Pdb)""" - - def help_quit(self): - self.help_q() - - def help_q(self): - print """q(uit) Quit from the debugger. - The program being executed is aborted.""" - - def help_whatis(self): - print """whatis arg - Prints the type of the argument.""" - - def help_EOF(self): - print """EOF - Handles the receipt of EOF as a command.""" - - def help_alias(self): - print """alias [name [command [parameter parameter ...] ]] - Creates an alias called 'name' the executes 'command'. The command - must *not* be enclosed in quotes. Replaceable parameters are - indicated by %1, %2, and so on, while %* is replaced by all the - parameters. If no command is given, the current alias for name - is shown. If no name is given, all aliases are listed. - - Aliases may be nested and can contain anything that can be - legally typed at the pdb prompt. Note! You *can* override - internal pdb commands with aliases! Those internal commands - are then hidden until the alias is removed. Aliasing is recursively - applied to the first word of the command line; all other words - in the line are left alone. - - Some useful aliases (especially when placed in the .pdbrc file) are: - - #Print instance variables (usage "pi classInst") - alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k] - - #Print instance variables in self - alias ps pi self - """ - - def help_unalias(self): - print """unalias name - Deletes the specified alias.""" - - def help_pdb(self): - help() - - def lookupmodule(self, filename): - """Helper function for break/clear parsing -- may be overridden.""" - root, ext = os.path.splitext(filename) - if ext == '': - filename = filename + '.py' - if os.path.isabs(filename): - return filename - for dirname in sys.path: - while os.path.islink(dirname): - dirname = os.readlink(dirname) - fullname = os.path.join(dirname, filename) - if os.path.exists(fullname): - return fullname - return None + + def __init__(self): + bdb.Bdb.__init__(self) + cmd.Cmd.__init__(self) + self.prompt = '(Pdb) ' + self.aliases = {} + # Try to load readline if it exists + try: + import readline + except ImportError: + pass + + # Read $HOME/.pdbrc and ./.pdbrc + self.rcLines = [] + if os.environ.has_key('HOME'): + envHome = os.environ['HOME'] + try: + rcFile = open(os.path.join(envHome, ".pdbrc")) + except IOError: + pass + else: + for line in rcFile.readlines(): + self.rcLines.append(line) + rcFile.close() + try: + rcFile = open(".pdbrc") + except IOError: + pass + else: + for line in rcFile.readlines(): + self.rcLines.append(line) + rcFile.close() + + def reset(self): + bdb.Bdb.reset(self) + self.forget() + + def forget(self): + self.lineno = None + self.stack = [] + self.curindex = 0 + self.curframe = None + + def setup(self, f, t): + self.forget() + self.stack, self.curindex = self.get_stack(f, t) + self.curframe = self.stack[self.curindex][0] + self.execRcLines() + + # Can be executed earlier than 'setup' if desired + def execRcLines(self): + if self.rcLines: + # Make local copy because of recursion + rcLines = self.rcLines + # executed only once + self.rcLines = [] + for line in rcLines: + line = line[:-1] + if len (line) > 0 and line[0] != '#': + self.onecmd (line) + + # Override Bdb methods (except user_call, for now) + + def user_line(self, frame): + """This function is called when we stop or break at this line.""" + self.interaction(frame, None) + + def user_return(self, frame, return_value): + """This function is called when a return trap is set here.""" + frame.f_locals['__return__'] = return_value + print '--Return--' + self.interaction(frame, None) + + def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): + """This function is called if an exception occurs, + but only if we are to stop at or just below this level.""" + frame.f_locals['__exception__'] = exc_type, exc_value + if type(exc_type) == type(''): + exc_type_name = exc_type + else: exc_type_name = exc_type.__name__ + print exc_type_name + ':', repr.repr(exc_value) + self.interaction(frame, exc_traceback) + + # General interaction function + + def interaction(self, frame, traceback): + self.setup(frame, traceback) + self.print_stack_entry(self.stack[self.curindex]) + self.cmdloop() + self.forget() + + def default(self, line): + if line[:1] == '!': line = line[1:] + locals = self.curframe.f_locals + globals = self.curframe.f_globals + try: + code = compile(line + '\n', '', 'single') + exec code in globals, locals + except: + t, v = sys.exc_info()[:2] + if type(t) == type(''): + exc_type_name = t + else: exc_type_name = t.__name__ + print '***', exc_type_name + ':', v + + def precmd(self, line): + """Handle alias expansion and ';;' separator.""" + if not line: + return line + args = string.split(line) + while self.aliases.has_key(args[0]): + line = self.aliases[args[0]] + ii = 1 + for tmpArg in args[1:]: + line = string.replace(line, "%" + str(ii), + tmpArg) + ii = ii + 1 + line = string.replace(line, "%*", + string.join(args[1:], ' ')) + args = string.split(line) + # split into ';;' separated commands + # unless it's an alias command + if args[0] != 'alias': + marker = string.find(line, ';;') + if marker >= 0: + # queue up everything after marker + next = string.lstrip(line[marker+2:]) + self.cmdqueue.append(next) + line = string.rstrip(line[:marker]) + return line + + # Command definitions, called by cmdloop() + # The argument is the remaining string on the command line + # Return true to exit from the command loop + + do_h = cmd.Cmd.do_help + + def do_EOF(self, arg): + return 0 # Don't die on EOF + + def do_break(self, arg, temporary = 0): + # break [ ([filename:]lineno | function) [, "condition"] ] + if not arg: + if self.breaks: # There's at least one + print "Num Type Disp Enb Where" + for bp in bdb.Breakpoint.bpbynumber: + if bp: + bp.bpprint() + return + # parse arguments; comma has lowest precedence + # and cannot occur in filename + filename = None + lineno = None + cond = None + comma = string.find(arg, ',') + if comma > 0: + # parse stuff after comma: "condition" + cond = string.lstrip(arg[comma+1:]) + arg = string.rstrip(arg[:comma]) + # parse stuff before comma: [filename:]lineno | function + colon = string.rfind(arg, ':') + if colon >= 0: + filename = string.rstrip(arg[:colon]) + f = self.lookupmodule(filename) + if not f: + print '*** ', `filename`, + print 'not found from sys.path' + return + else: + filename = f + arg = string.lstrip(arg[colon+1:]) + try: + lineno = int(arg) + except ValueError, msg: + print '*** Bad lineno:', arg + return + else: + # no colon; can be lineno or function + try: + lineno = int(arg) + except ValueError: + try: + func = eval(arg, + self.curframe.f_globals, + self.curframe.f_locals) + except: + func = arg + try: + if hasattr(func, 'im_func'): + func = func.im_func + code = func.func_code + lineno = code.co_firstlineno + filename = code.co_filename + except: + # last thing to try + (ok, filename, ln) = self.lineinfo(arg) + if not ok: + print '*** The specified object', + print `arg`, + print 'is not a function' + print ('or was not found ' + 'along sys.path.') + return + lineno = int(ln) + if not filename: + filename = self.defaultFile() + # Check for reasonable breakpoint + line = self.checkline(filename, lineno) + if line: + # now set the break point + err = self.set_break(filename, line, temporary, cond) + if err: print '***', err + else: + bp = self.get_breaks(filename, line)[-1] + print "Breakpoint %d at %s:%d" % (bp.number, + bp.file, + bp.line) + + # To be overridden in derived debuggers + def defaultFile(self): + """Produce a reasonable default.""" + filename = self.curframe.f_code.co_filename + if filename == '' and mainpyfile: + filename = mainpyfile + return filename + + do_b = do_break + + def do_tbreak(self, arg): + self.do_break(arg, 1) + + def lineinfo(self, identifier): + failed = (None, None, None) + # Input is identifier, may be in single quotes + idstring = string.split(identifier, "'") + if len(idstring) == 1: + # not in single quotes + id = string.strip(idstring[0]) + elif len(idstring) == 3: + # quoted + id = string.strip(idstring[1]) + else: + return failed + if id == '': return failed + parts = string.split(id, '.') + # Protection for derived debuggers + if parts[0] == 'self': + del parts[0] + if len(parts) == 0: + return failed + # Best first guess at file to look at + fname = self.defaultFile() + if len(parts) == 1: + item = parts[0] + else: + # More than one part. + # First is module, second is method/class + f = self.lookupmodule(parts[0]) + if f: + fname = f + item = parts[1] + answer = find_function(item, fname) + return answer or failed + + def checkline(self, filename, lineno): + """Return line number of first line at or after input + argument such that if the input points to a 'def', the + returned line number is the first + non-blank/non-comment line to follow. If the input + points to a blank or comment line, return 0. At end + of file, also return 0.""" + + line = linecache.getline(filename, lineno) + if not line: + print 'End of file' + return 0 + line = string.strip(line) + # Don't allow setting breakpoint at a blank line + if ( not line or (line[0] == '#') or + (line[:3] == '"""') or line[:3] == "'''" ): + print '*** Blank or comment' + return 0 + # When a file is read in and a breakpoint is at + # the 'def' statement, the system stops there at + # code parse time. We don't want that, so all breakpoints + # set at 'def' statements are moved one line onward + if line[:3] == 'def': + instr = '' + brackets = 0 + while 1: + skipone = 0 + for c in line: + if instr: + if skipone: + skipone = 0 + elif c == '\\': + skipone = 1 + elif c == instr: + instr = '' + elif c == '#': + break + elif c in ('"',"'"): + instr = c + elif c in ('(','{','['): + brackets = brackets + 1 + elif c in (')','}',']'): + brackets = brackets - 1 + lineno = lineno+1 + line = linecache.getline(filename, lineno) + if not line: + print 'end of file' + return 0 + line = string.strip(line) + if not line: continue # Blank line + if brackets <= 0 and line[0] not in ('#','"',"'"): + break + return lineno + + def do_enable(self, arg): + args = string.split(arg) + for i in args: + bp = bdb.Breakpoint.bpbynumber[int(i)] + if bp: + bp.enable() + + def do_disable(self, arg): + args = string.split(arg) + for i in args: + bp = bdb.Breakpoint.bpbynumber[int(i)] + if bp: + bp.disable() + + def do_condition(self, arg): + # arg is breakpoint number and condition + args = string.split(arg, ' ', 1) + bpnum = int(string.strip(args[0])) + try: + cond = args[1] + except: + cond = None + bp = bdb.Breakpoint.bpbynumber[bpnum] + if bp: + bp.cond = cond + if not cond: + print 'Breakpoint', bpnum, + print 'is now unconditional.' + + def do_ignore(self,arg): + """arg is bp number followed by ignore count.""" + args = string.split(arg) + bpnum = int(string.strip(args[0])) + try: + count = int(string.strip(args[1])) + except: + count = 0 + bp = bdb.Breakpoint.bpbynumber[bpnum] + if bp: + bp.ignore = count + if (count > 0): + reply = 'Will ignore next ' + if (count > 1): + reply = reply + '%d crossings' % count + else: + reply = reply + '1 crossing' + print reply + ' of breakpoint %d.' % bpnum + else: + print 'Will stop next time breakpoint', + print bpnum, 'is reached.' + + def do_clear(self, arg): + """Three possibilities, tried in this order: + clear -> clear all breaks, ask for confirmation + clear file:lineno -> clear all breaks at file:lineno + clear bpno bpno ... -> clear breakpoints by number""" + if not arg: + try: + reply = raw_input('Clear all breaks? ') + except EOFError: + reply = 'no' + reply = string.lower(string.strip(reply)) + if reply in ('y', 'yes'): + self.clear_all_breaks() + return + if ':' in arg: + # Make sure it works for "clear C:\foo\bar.py:12" + i = string.rfind(arg, ':') + filename = arg[:i] + arg = arg[i+1:] + try: + lineno = int(arg) + except: + err = "Invalid line number (%s)" % arg + else: + err = self.clear_break(filename, lineno) + if err: print '***', err + return + numberlist = string.split(arg) + for i in numberlist: + err = self.clear_bpbynumber(i) + if err: + print '***', err + else: + print 'Deleted breakpoint %s ' % (i,) + do_cl = do_clear # 'c' is already an abbreviation for 'continue' + + def do_where(self, arg): + self.print_stack_trace() + do_w = do_where + + def do_up(self, arg): + if self.curindex == 0: + print '*** Oldest frame' + else: + self.curindex = self.curindex - 1 + self.curframe = self.stack[self.curindex][0] + self.print_stack_entry(self.stack[self.curindex]) + self.lineno = None + do_u = do_up + + def do_down(self, arg): + if self.curindex + 1 == len(self.stack): + print '*** Newest frame' + else: + self.curindex = self.curindex + 1 + self.curframe = self.stack[self.curindex][0] + self.print_stack_entry(self.stack[self.curindex]) + self.lineno = None + do_d = do_down + + def do_step(self, arg): + self.set_step() + return 1 + do_s = do_step + + def do_next(self, arg): + self.set_next(self.curframe) + return 1 + do_n = do_next + + def do_return(self, arg): + self.set_return(self.curframe) + return 1 + do_r = do_return + + def do_continue(self, arg): + self.set_continue() + return 1 + do_c = do_cont = do_continue + + def do_quit(self, arg): + self.set_quit() + return 1 + do_q = do_quit + + def do_args(self, arg): + f = self.curframe + co = f.f_code + dict = f.f_locals + n = co.co_argcount + if co.co_flags & 4: n = n+1 + if co.co_flags & 8: n = n+1 + for i in range(n): + name = co.co_varnames[i] + print name, '=', + if dict.has_key(name): print dict[name] + else: print "*** undefined ***" + do_a = do_args + + def do_retval(self, arg): + if self.curframe.f_locals.has_key('__return__'): + print self.curframe.f_locals['__return__'] + else: + print '*** Not yet returned!' + do_rv = do_retval + + def do_p(self, arg): + try: + value = eval(arg, self.curframe.f_globals, + self.curframe.f_locals) + except: + t, v = sys.exc_info()[:2] + if type(t) == type(''): + exc_type_name = t + else: exc_type_name = t.__name__ + print '***', exc_type_name + ':', `v` + return + + print `value` + + def do_list(self, arg): + self.lastcmd = 'list' + last = None + if arg: + try: + x = eval(arg, {}, {}) + if type(x) == type(()): + first, last = x + first = int(first) + last = int(last) + if last < first: + # Assume it's a count + last = first + last + else: + first = max(1, int(x) - 5) + except: + print '*** Error in argument:', `arg` + return + elif self.lineno is None: + first = max(1, self.curframe.f_lineno - 5) + else: + first = self.lineno + 1 + if last is None: + last = first + 10 + filename = self.curframe.f_code.co_filename + breaklist = self.get_file_breaks(filename) + try: + for lineno in range(first, last+1): + line = linecache.getline(filename, lineno) + if not line: + print '[EOF]' + break + else: + s = string.rjust(`lineno`, 3) + if len(s) < 4: s = s + ' ' + if lineno in breaklist: s = s + 'B' + else: s = s + ' ' + if lineno == self.curframe.f_lineno: + s = s + '->' + print s + '\t' + line, + self.lineno = lineno + except KeyboardInterrupt: + pass + do_l = do_list + + def do_whatis(self, arg): + try: + value = eval(arg, self.curframe.f_globals, + self.curframe.f_locals) + except: + t, v = sys.exc_info()[:2] + if type(t) == type(''): + exc_type_name = t + else: exc_type_name = t.__name__ + print '***', exc_type_name + ':', `v` + return + code = None + # Is it a function? + try: code = value.func_code + except: pass + if code: + print 'Function', code.co_name + return + # Is it an instance method? + try: code = value.im_func.func_code + except: pass + if code: + print 'Method', code.co_name + return + # None of the above... + print type(value) + + def do_alias(self, arg): + args = string.split (arg) + if len(args) == 0: + keys = self.aliases.keys() + keys.sort() + for alias in keys: + print "%s = %s" % (alias, self.aliases[alias]) + return + if self.aliases.has_key(args[0]) and len (args) == 1: + print "%s = %s" % (args[0], self.aliases[args[0]]) + else: + self.aliases[args[0]] = string.join(args[1:], ' ') + + def do_unalias(self, arg): + args = string.split (arg) + if len(args) == 0: return + if self.aliases.has_key(args[0]): + del self.aliases[args[0]] + + # Print a traceback starting at the top stack frame. + # The most recently entered frame is printed last; + # this is different from dbx and gdb, but consistent with + # the Python interpreter's stack trace. + # It is also consistent with the up/down commands (which are + # compatible with dbx and gdb: up moves towards 'main()' + # and down moves towards the most recent stack frame). + + def print_stack_trace(self): + try: + for frame_lineno in self.stack: + self.print_stack_entry(frame_lineno) + except KeyboardInterrupt: + pass + + def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix): + frame, lineno = frame_lineno + if frame is self.curframe: + print '>', + else: + print ' ', + print self.format_stack_entry(frame_lineno, prompt_prefix) + + + # Help methods (derived from pdb.doc) + + def help_help(self): + self.help_h() + + def help_h(self): + print """h(elp) +Without argument, print the list of available commands. +With a command name as argument, print help about that command +"help pdb" pipes the full documentation file to the $PAGER +"help exec" gives help on the ! command""" + + def help_where(self): + self.help_w() + + def help_w(self): + print """w(here) +Print a stack trace, with the most recent frame at the bottom. +An arrow indicates the "current frame", which determines the +context of most commands.""" + + def help_down(self): + self.help_d() + + def help_d(self): + print """d(own) +Move the current frame one level down in the stack trace +(to an older frame).""" + + def help_up(self): + self.help_u() + + def help_u(self): + print """u(p) +Move the current frame one level up in the stack trace +(to a newer frame).""" + + def help_break(self): + self.help_b() + + def help_b(self): + print """b(reak) ([file:]lineno | function) [, condition] +With a line number argument, set a break there in the current +file. With a function name, set a break at first executable line +of that function. Without argument, list all breaks. If a second +argument is present, it is a string specifying an expression +which must evaluate to true before the breakpoint is honored. + +The line number may be prefixed with a filename and a colon, +to specify a breakpoint in another file (probably one that +hasn't been loaded yet). The file is searched for on sys.path; +the .py suffix may be omitted.""" + + def help_clear(self): + self.help_cl() + + def help_cl(self): + print "cl(ear) filename:lineno" + print """cl(ear) [bpnumber [bpnumber...]] +With a space separated list of breakpoint numbers, clear +those breakpoints. Without argument, clear all breaks (but +first ask confirmation). With a filename:lineno argument, +clear all breaks at that line in that file. + +Note that the argument is different from previous versions of +the debugger (in python distributions 1.5.1 and before) where +a linenumber was used instead of either filename:lineno or +breakpoint numbers.""" + + def help_tbreak(self): + print """tbreak same arguments as break, but breakpoint is +removed when first hit.""" + + def help_enable(self): + print """enable bpnumber [bpnumber ...] +Enables the breakpoints given as a space separated list of +bp numbers.""" + + def help_disable(self): + print """disable bpnumber [bpnumber ...] +Disables the breakpoints given as a space separated list of +bp numbers.""" + + def help_ignore(self): + print """ignore bpnumber count +Sets the ignore count for the given breakpoint number. A breakpoint +becomes active when the ignore count is zero. When non-zero, the +count is decremented each time the breakpoint is reached and the +breakpoint is not disabled and any associated condition evaluates +to true.""" + + def help_condition(self): + print """condition bpnumber str_condition +str_condition is a string specifying an expression which +must evaluate to true before the breakpoint is honored. +If str_condition is absent, any existing condition is removed; +i.e., the breakpoint is made unconditional.""" + + def help_step(self): + self.help_s() + + def help_s(self): + print """s(tep) +Execute the current line, stop at the first possible occasion +(either in a function that is called or in the current function).""" + + def help_next(self): + self.help_n() + + def help_n(self): + print """n(ext) +Continue execution until the next line in the current function +is reached or it returns.""" + + def help_return(self): + self.help_r() + + def help_r(self): + print """r(eturn) +Continue execution until the current function returns.""" + + def help_continue(self): + self.help_c() + + def help_cont(self): + self.help_c() + + def help_c(self): + print """c(ont(inue)) +Continue execution, only stop when a breakpoint is encountered.""" + + def help_list(self): + self.help_l() + + def help_l(self): + print """l(ist) [first [,last]] +List source code for the current file. +Without arguments, list 11 lines around the current line +or continue the previous listing. +With one argument, list 11 lines starting at that line. +With two arguments, list the given range; +if the second argument is less than the first, it is a count.""" + + def help_args(self): + self.help_a() + + def help_a(self): + print """a(rgs) +Print the arguments of the current function.""" + + def help_p(self): + print """p expression +Print the value of the expression.""" + + def help_exec(self): + print """(!) statement +Execute the (one-line) statement in the context of +the current stack frame. +The exclamation point can be omitted unless the first word +of the statement resembles a debugger command. +To assign to a global variable you must always prefix the +command with a 'global' command, e.g.: +(Pdb) global list_options; list_options = ['-l'] +(Pdb)""" + + def help_quit(self): + self.help_q() + + def help_q(self): + print """q(uit) Quit from the debugger. +The program being executed is aborted.""" + + def help_whatis(self): + print """whatis arg +Prints the type of the argument.""" + + def help_EOF(self): + print """EOF +Handles the receipt of EOF as a command.""" + + def help_alias(self): + print """alias [name [command [parameter parameter ...] ]] +Creates an alias called 'name' the executes 'command'. The command +must *not* be enclosed in quotes. Replaceable parameters are +indicated by %1, %2, and so on, while %* is replaced by all the +parameters. If no command is given, the current alias for name +is shown. If no name is given, all aliases are listed. + +Aliases may be nested and can contain anything that can be +legally typed at the pdb prompt. Note! You *can* override +internal pdb commands with aliases! Those internal commands +are then hidden until the alias is removed. Aliasing is recursively +applied to the first word of the command line; all other words +in the line are left alone. + +Some useful aliases (especially when placed in the .pdbrc file) are: + +#Print instance variables (usage "pi classInst") +alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k] + +#Print instance variables in self +alias ps pi self +""" + + def help_unalias(self): + print """unalias name +Deletes the specified alias.""" + + def help_pdb(self): + help() + + def lookupmodule(self, filename): + """Helper function for break/clear parsing -- may be overridden.""" + root, ext = os.path.splitext(filename) + if ext == '': + filename = filename + '.py' + if os.path.isabs(filename): + return filename + for dirname in sys.path: + while os.path.islink(dirname): + dirname = os.readlink(dirname) + fullname = os.path.join(dirname, filename) + if os.path.exists(fullname): + return fullname + return None # Simplified interface def run(statement, globals=None, locals=None): - Pdb().run(statement, globals, locals) + Pdb().run(statement, globals, locals) def runeval(expression, globals=None, locals=None): - return Pdb().runeval(expression, globals, locals) + return Pdb().runeval(expression, globals, locals) def runctx(statement, globals, locals): - # B/W compatibility - run(statement, globals, locals) + # B/W compatibility + run(statement, globals, locals) def runcall(*args): - return apply(Pdb().runcall, args) + return apply(Pdb().runcall, args) def set_trace(): - Pdb().set_trace() + Pdb().set_trace() # Post-Mortem interface def post_mortem(t): - p = Pdb() - p.reset() - while t.tb_next is not None: - t = t.tb_next - p.interaction(t.tb_frame, t) + p = Pdb() + p.reset() + while t.tb_next is not None: + t = t.tb_next + p.interaction(t.tb_frame, t) def pm(): - post_mortem(sys.last_traceback) + post_mortem(sys.last_traceback) # Main program for testing @@ -908,37 +908,37 @@ def pm(): TESTCMD = 'import x; x.main()' def test(): - run(TESTCMD) + run(TESTCMD) # print help def help(): - for dirname in sys.path: - fullname = os.path.join(dirname, 'pdb.doc') - if os.path.exists(fullname): - sts = os.system('${PAGER-more} '+fullname) - if sts: print '*** Pager exit status:', sts - break - else: - print 'Sorry, can\'t find the help file "pdb.doc"', - print 'along the Python search path' + for dirname in sys.path: + fullname = os.path.join(dirname, 'pdb.doc') + if os.path.exists(fullname): + sts = os.system('${PAGER-more} '+fullname) + if sts: print '*** Pager exit status:', sts + break + else: + print 'Sorry, can\'t find the help file "pdb.doc"', + print 'along the Python search path' mainmodule = '' mainpyfile = '' # When invoked as main program, invoke the debugger on a script if __name__=='__main__': - if not sys.argv[1:]: - print "usage: pdb.py scriptfile [arg] ..." - sys.exit(2) + if not sys.argv[1:]: + print "usage: pdb.py scriptfile [arg] ..." + sys.exit(2) - mainpyfile = filename = sys.argv[1] # Get script filename - if not os.path.exists(filename): - print 'Error:', `filename`, 'does not exist' - sys.exit(1) - mainmodule = os.path.basename(filename) - del sys.argv[0] # Hide "pdb.py" from argument list + mainpyfile = filename = sys.argv[1] # Get script filename + if not os.path.exists(filename): + print 'Error:', `filename`, 'does not exist' + sys.exit(1) + mainmodule = os.path.basename(filename) + del sys.argv[0] # Hide "pdb.py" from argument list - # Insert script directory in front of module search path - sys.path.insert(0, os.path.dirname(filename)) + # Insert script directory in front of module search path + sys.path.insert(0, os.path.dirname(filename)) - run('execfile(' + `filename` + ')') + run('execfile(' + `filename` + ')') diff --git a/Lib/pickle.py b/Lib/pickle.py index fb9448e9771..45fd0f1560a 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -123,7 +123,7 @@ class Pickler: return LONG_BINGET + s return GET + `i` + '\n' - + def save(self, object, pers_save = 0): memo = self.memo @@ -134,7 +134,7 @@ class Pickler: return d = id(object) - + t = type(object) if ((t is TupleType) and (len(object) == 0)): @@ -179,14 +179,14 @@ class Pickler: "tuple" % reduce l = len(tup) - + if ((l != 2) and (l != 3)): raise PicklingError, "tuple returned by %s must contain " \ "only two or three elements" % reduce callable = tup[0] arg_tup = tup[1] - + if (l > 2): state = tup[2] else: @@ -196,7 +196,7 @@ class Pickler: raise PicklingError, "Second element of tuple returned " \ "by %s must be a tuple" % reduce - self.save_reduce(callable, arg_tup, state) + self.save_reduce(callable, arg_tup, state) memo_len = len(memo) self.write(self.put(memo_len)) memo[d] = (memo_len, object) @@ -224,7 +224,7 @@ class Pickler: save(callable) save(arg_tup) write(REDUCE) - + if (state is not None): save(state) write(BUILD) @@ -317,7 +317,7 @@ class Pickler: if (self.bin): write(POP_MARK + self.get(memo[d][0])) return - + write(POP * (len(object) + 1) + self.get(memo[d][0])) return @@ -352,7 +352,7 @@ class Pickler: for element in object: save(element) - + if (not using_appends): write(APPEND) @@ -542,7 +542,7 @@ class Unpickler: def load_binpersid(self): stack = self.stack - + pid = stack[-1] del stack[-1] @@ -568,7 +568,7 @@ class Unpickler: def load_binint2(self): self.append(mloads('i' + self.read(2) + '\000\000')) dispatch[BININT2] = load_binint2 - + def load_long(self): self.append(long(self.readline()[:-1], 0)) dispatch[LONG] = load_long @@ -710,7 +710,7 @@ class Unpickler: k = self.marker() klass = stack[k + 1] del stack[k + 1] - args = tuple(stack[k + 1:]) + args = tuple(stack[k + 1:]) del stack[k:] instantiated = 0 if (not args and type(klass) is ClassType and @@ -726,7 +726,7 @@ class Unpickler: if not instantiated: value = apply(klass, args) self.append(value) - dispatch[OBJ] = load_obj + dispatch[OBJ] = load_obj def load_global(self): module = self.readline()[:-1] @@ -761,8 +761,8 @@ class Unpickler: safe = None if (not safe): - raise UnpicklingError, "%s is not safe for " \ - "unpickling" % callable + raise UnpicklingError, "%s is not safe for " \ + "unpickling" % callable if arg_tup is None: value = callable.__basicnew__() @@ -829,7 +829,7 @@ class Unpickler: del stack[mark:] dispatch[APPENDS] = load_appends - + def load_setitem(self): stack = self.stack value = stack[-1] diff --git a/Lib/pipes.py b/Lib/pipes.py index 3aa1bf1f221..77a57e815c9 100644 --- a/Lib/pipes.py +++ b/Lib/pipes.py @@ -69,229 +69,229 @@ import string # Conversion step kinds -FILEIN_FILEOUT = 'ff' # Must read & write real files -STDIN_FILEOUT = '-f' # Must write a real file -FILEIN_STDOUT = 'f-' # Must read a real file -STDIN_STDOUT = '--' # Normal pipeline element -SOURCE = '.-' # Must be first, writes stdout -SINK = '-.' # Must be last, reads stdin +FILEIN_FILEOUT = 'ff' # Must read & write real files +STDIN_FILEOUT = '-f' # Must write a real file +FILEIN_STDOUT = 'f-' # Must read a real file +STDIN_STDOUT = '--' # Normal pipeline element +SOURCE = '.-' # Must be first, writes stdout +SINK = '-.' # Must be last, reads stdin stepkinds = [FILEIN_FILEOUT, STDIN_FILEOUT, FILEIN_STDOUT, STDIN_STDOUT, \ - SOURCE, SINK] + SOURCE, SINK] class Template: - """Class representing a pipeline template.""" + """Class representing a pipeline template.""" - def __init__(self): - """Template() returns a fresh pipeline template.""" - self.debugging = 0 - self.reset() + def __init__(self): + """Template() returns a fresh pipeline template.""" + self.debugging = 0 + self.reset() - def __repr__(self): - """t.__repr__() implements `t`.""" - return '