blob: 327d8b42d877ad92681e2da3be15146a170151c1 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001# epydoc -- Backwards compatibility
2#
3# Copyright (C) 2005 Edward Loper
4# Author: Edward Loper <edloper@loper.org>
5# URL: <http://epydoc.sf.net>
6#
7# $Id: util.py 956 2006-03-10 01:30:51Z edloper $
8
9"""
10Backwards compatibility with previous versions of Python.
11
12This module provides backwards compatibility by defining several
13functions and classes that were not available in earlier versions of
14Python. Intented usage:
15
16 >>> from epydoc.compat import *
17
18Currently, epydoc requires Python 2.3+.
19"""
20__docformat__ = 'epytext'
21
22######################################################################
23#{ New in Python 2.4
24######################################################################
25
26# set
27try:
28 set
29except NameError:
30 try:
31 from sets import Set as set, ImmutableSet as frozenset
32 except ImportError:
33 pass # use fallback, in the next section.
34
35# sorted
36try:
37 sorted
38except NameError:
39 def sorted(iterable, cmp=None, key=None, reverse=False):
40 if key is None:
41 elts = list(iterable)
42 else:
43 elts = [(key(v), v) for v in iterable]
44
45 if reverse: elts.reverse() # stable sort.
46 if cmp is None: elts.sort()
47 else: elts.sort(cmp)
48 if reverse: elts.reverse()
49
50 if key is None:
51 return elts
52 else:
53 return [v for (k,v) in elts]
54
55# reversed
56try:
57 reversed
58except NameError:
59 def reversed(iterable):
60 elts = list(iterable)
61 elts.reverse()
62 return elts
63
64######################################################################
65#{ New in Python 2.3
66######################################################################
67# Below is my initial attempt at backporting enough code that
68# epydoc 3 would run under python 2.2. However, I'm starting
69# to think that it's not worth the trouble. At the very least,
70# epydoc's current unicode handling still doesn't work under
71# 2.2 (after the backports below), since the 'xmlcharrefreplace'
72# error handler was introduced in python 2.3.
73
74# # basestring
75# try:
76# basestring
77# except NameError:
78# basestring = (str, unicode)
79
80# # sum
81# try:
82# sum
83# except NameError:
84# def _add(a,b): return a+b
85# def sum(vals): return reduce(_add, vals, 0)
86
87# # True & False
88# try:
89# True
90# except NameError:
91# True = 1
92# False = 0
93
94# # enumerate
95# try:
96# enumerate
97# except NameError:
98# def enumerate(iterable):
99# lst = list(iterable)
100# return zip(range(len(lst)), lst)
101
102# # set
103# try:
104# set
105# except NameError:
106# class set(dict):
107# def __init__(self, elts=()):
108# dict.__init__(self, [(e,1) for e in elts])
109# def __repr__(self):
110# return 'set(%r)' % list(self)
111# def add(self, key): self[key] = 1
112# def copy(self):
113# return set(dict.copy(self))
114# def difference(self, other):
115# return set([v for v in self if v not in other])
116# def difference_udpate(self, other):
117# newval = self.difference(other)
118# self.clear(); self.update(newval)
119# def discard(self, elt):
120# try: del self[elt]
121# except: pass
122# def intersection(self, other):
123# return self.copy().update(other)
124# def intersection_update(self, other):
125# newval = self.intersection(other)
126# self.clear(); self.update(newval)
127# def issubset(self, other):
128# for elt in self:
129# if elt not in other: return False
130# return True
131# def issuperset(self, other):
132# for elt in other:
133# if elt not in self: return False
134# return True
135# def pop(self): self.popitem()[0]
136# def remove(self, elt): del self[elt]
137# def symmetric_difference(self, other):
138# return set([v for v in list(self)+list(other)
139# if (v in self)^(v in other)])
140# def symmatric_difference_update(self, other):
141# newval = self.symmetric_difference(other)
142# self.clear(); self.update(newval)
143# def union(self, other):
144# return set([v for v in list(self)+list(other)
145# if (v in self) or (v in other)])
146# def union_update(self, other):
147# newval = self.union(other)
148# self.clear(); self.update(newval)
149# def update(self, other):
150# dict.update(self, set(other))
151
152# # optparse module
153# try:
154# import optparse
155# except ImportError:
156# import new, sys, getopt
157# class _OptionVals:
158# def __init__(self, vals): self.__dict__.update(vals)
159# class OptionParser:
160# def __init__(self, usage=None, version=None):
161# self.usage = usage
162# self.version = version
163# self.shortops = ['h']
164# self.longops = []
165# self.option_specs = {}
166# self.defaults = {}
167# def fail(self, message, exitval=1):
168# print >>sys.stderr, message
169# system.exit(exitval)
170# def add_option_group(self, group): pass
171# def set_defaults(self, **defaults):
172# self.defaults = defaults.copy()
173# def parse_args(self):
174# try:
175# (opts, names) = getopt.getopt(sys.argv[1:],
176# ''.join(self.shortops),
177# self.longops)
178# except getopt.GetoptError, e:
179# self.fail(e)
180
181# options = self.defaults.copy()
182# for (opt,val) in opts:
183# if opt == '-h':
184# self.fail('No help available')
185# if opt not in self.option_specs:
186# self.fail('Unknown option %s' % opt)
187# (action, dest, const) = self.option_specs[opt]
188# if action == 'store':
189# options[dest] = val
190# elif action == 'store_const':
191# options[dest] = const
192# elif action == 'count':
193# options[dest] = options.get(dest,0)+1
194# elif action == 'append':
195# options.setdefault(dest, []).append(val)
196# else:
197# self.fail('unsupported action: %s' % action)
198# for (action,dest,const) in self.option_specs.values():
199# if dest not in options:
200# if action == 'count': options[dest] = 0
201# elif action == 'append': options[dest] = []
202# else: options[dest] = None
203# for name in names:
204# if name.startswith('-'):
205# self.fail('names must follow options')
206# return _OptionVals(options), names
207# class OptionGroup:
208# def __init__(self, optparser, name):
209# self.optparser = optparser
210# self.name = name
211
212# def add_option(self, *args, **kwargs):
213# action = 'store'
214# dest = None
215# const = None
216# for (key,val) in kwargs.items():
217# if key == 'action': action = val
218# elif key == 'dest': dest = val
219# elif key == 'const': const = val
220# elif key in ('help', 'metavar'): pass
221# else: self.fail('unsupported: %s' % key)
222
223# if action not in ('store_const', 'store_true', 'store_false',
224# 'store', 'count', 'append'):
225# self.fail('unsupported action: %s' % action)
226
227# optparser = self.optparser
228# for arg in args:
229# if arg.startswith('--'):
230# optparser.longops.append(arg[2:])
231# elif arg.startswith('-') and len(arg)==2:
232# optparser.shortops += arg[1]
233# if action in ('store', 'append'):
234# optparser.shortops += ':'
235# else:
236# self.fail('bad option name %s' % arg)
237# if action == 'store_true':
238# (action, const) = ('store_const', True)
239# if action == 'store_false':
240# (action, const) = ('store_const', False)
241# optparser.option_specs[arg] = (action, dest, const)
242
243# # Install a fake module.
244# optparse = new.module('optparse')
245# optparse.OptionParser = OptionParser
246# optparse.OptionGroup = OptionGroup
247# sys.modules['optparse'] = optparse
248# # Clean up
249# del OptionParser, OptionGroup
250