| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame^] | 1 | # 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 | """ |
| 10 | Backwards compatibility with previous versions of Python. |
| 11 | |
| 12 | This module provides backwards compatibility by defining several |
| 13 | functions and classes that were not available in earlier versions of |
| 14 | Python. Intented usage: |
| 15 | |
| 16 | >>> from epydoc.compat import * |
| 17 | |
| 18 | Currently, epydoc requires Python 2.3+. |
| 19 | """ |
| 20 | __docformat__ = 'epytext' |
| 21 | |
| 22 | ###################################################################### |
| 23 | #{ New in Python 2.4 |
| 24 | ###################################################################### |
| 25 | |
| 26 | # set |
| 27 | try: |
| 28 | set |
| 29 | except 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 |
| 36 | try: |
| 37 | sorted |
| 38 | except 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 |
| 56 | try: |
| 57 | reversed |
| 58 | except 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 | |