root/django/trunk/contrib/tinyid.py

Revision 91, 4.1 kB (checked in by steadicat, 13 months ago)

TinyId? now doesn't use ambiguous characters like o, 0, 1, l, i.

  • Property svn:keywords set to Id
Line 
1import string
2
3def rebase(i, frombase=None, tobase=None, fromalphabet=None, toalphabet=None, resize=1, too_big=40000, debug=False):
4#     ''' if frombase is not specified, it is guessed from the type and/or char in i with highest ord.
5#         tobase defaults to [10, 2][frombase == 10].
6#         the alphabets are map(chr, range(256)) if its base is between 62 and 255;
7#         otherwise, string.digits+string.letters.
8#         always returns a string which is also valid input.
9#         valid bases are ints in range(-256, 257).
10#         alphabets must be subscriptable, and can only contain str's.
11#         invalid tobases are replied with 'why?'; rebase('why?') == '217648673'.
12#         returned string is zfilled to the next largest multiple of resize
13#     '''
14    if frombase == None:
15        if isinstance(i, (int, long)):
16            frombase = 10
17        elif isinstance(i, str):
18            a = str(i)
19            if any([(chr(x) in a) for x in range(ord('0')) + range(58, 65) + range(91, 97) + range(123, 256)]):
20                frombase = max(map(ord, a)) + 1
21            else:
22                frombase = max(map((string.digits + string.letters).index, a)) + 1
23    if tobase == None:
24        tobase = [10, 2][frombase == 10]
25    # got bases, ensuring that everything is an int
26    tobase = int(tobase)
27    frombase = int(frombase)
28    abstobase = abs(tobase)
29    absfrombase = abs(frombase)
30    if absfrombase in [0, 1]:
31        i = len(str(i))
32    elif 2 <= frombase <= 36:
33        # may be difficult to translate to C
34        i = int(str(i), frombase)
35    else:
36        i = str(i)
37        n = 0
38        if fromalphabet == None:
39            if 62 <= absfrombase <= 256:
40                fromalphabet = map(chr, range(256))
41            else:
42                fromalphabet = string.digits + string.letters
43        fromalphabet = fromalphabet[:absfrombase]
44        for j in range(len(i)):
45            n += (frombase ** j) * fromalphabet.index(i[-1-j])
46        i = n
47    # got ints, converting to tobase
48    if debug: print 'converting %d from base %d to %d' % (i, frombase, tobase)
49    if abstobase in [0, 1]:
50        return '0' * ((i > 0) and int(i) or 0)
51    elif abstobase > 256:
52        return 'why?'
53    # if execution gets here, we might want the result to be zfilled to a multiple of resize
54    r = ''
55    if tobase == 10:
56        r = str(i)
57    else:
58        if i < 0:
59            print 'negative',
60            i = -i
61        if toalphabet is None:
62            if 62 <= abstobase <= 256:
63                toalphabet = map(chr, range(abstobase))
64            else:
65                toalphabet = (string.digits + string.letters)[:abstobase]
66        if tobase < 0:
67            i = -i
68        j = 0
69        while i != 0:
70            r = toalphabet[i % tobase] + r
71            i /= tobase
72            j += 1
73            if j >= too_big: raise "call again; set too_big bigger"
74    if resize > 1:
75        if 62 <= abstobase <= 256:
76            r = toalphabet[0] * (resize - (len(r) % resize)) + r
77        else:
78            r = r.zfill(len(r) + resize - (len(r) % resize))
79    return r
80
81#             123456789
82#                       abcdefghjkmnpqrstuvwxyz
83
84oascii = r"""                                 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                                                                                                                 """
85ascii = r"""                                 !"#$%&'()*+,-./9abcdefghj:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`kmnpqrstuvwxyz12345678wxyz{|}~                                                                                                                                 """
86iascii = r"""                                 !"#$%&'()*+,-./jopqrstuv0:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`12345678 9a bc defghijklmn{|}~                                                                                                                                 """
87def tinyid(id):
88    return rebase(id, 10, 32).translate(ascii)
89
90def reverseTinyid(tinyid):
91    return int(rebase(str(tinyid).translate(iascii), 32, 10))
Note: See TracBrowser for help on using the browser.