caellion-python-commons
base36.py
Go to the documentation of this file.
1 """!
2 This module provides utlilities related to converting to/from base36 encoding.
3 """
4 
5 
7  """!
8  This exception is raised when custom character set length .
9  """
10 
11  pass
12 
13 
15  """!
16  This exception is raised when more than exactly one instance of a given field is contained within field list.
17  """
18 
19  pass
20 
21 
22 class InvalidInputStringException(Exception):
23  """!
24  This exception is raised when encountering a character not defined in custom charset in input string.
25  """
26 
27  pass
28 
29 
31  """!
32  This exception is raised when non-positive integer is passed to encode function.
33  """
34 
35  pass
36 
37 
38 class ValueTooLargeException(Exception):
39  """!
40  This exception is raised when encountering an integer over maximum size of 16 bytes.
41  """
42 
43  pass
44 
45 
47  """!
48  This class provides methods allowing conversion between integer, hexadecimal integer and base36 strings.
49  """
50 
51  # Custom charset to use with this instance of Base36Coder
52  custom_charset = None
53 
54  def __init__(self, custom_charset="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
55  """!
56  Initialize coder.
57 
58  @param custom_charset custom character set to use with the coder
59 
60  @throws InvalidCustomCharsetLengthException
61  @throws InvalidCustomCharsetException
62  """
63  if len(custom_charset) != 36:
65  "Custom charset is not exactly 36 characters long")
66 
67  xchk = []
68  idx = 0
69  for x in custom_charset:
70  if x not in xchk:
71  xchk.append(x)
72  idx += 1
73  else:
74  idxf = custom_charset.find(x)
76  "Character '%s' at position %s, first appeared at position %s is repeated in custom charset" % (x, idx, idxf))
77 
78  self.custom_charsetcustom_charset = custom_charset
79 
80  def to_standard_charset(self, unformatted):
81  """!
82  Converts custom charset to standard charset
83 
84  @param unformatted Base36 string in custom charset encoding
85 
86  @returns Base36 string in standardized format
87 
88  @throws InvalidInputStringException
89  """
90  std_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
91  formatted = ""
92 
93  for symbol in unformatted:
94  idx = self.custom_charsetcustom_charset.find(symbol)
95 
96  if idx == -1:
98  "Unexpected '%s' in input string." % symbol)
99  else:
100  formatted += std_charset[idx]
101 
102  return formatted
103 
104  def to_custom_charset(self, unformatted):
105  """!
106  Converts standard charset to custom charset
107 
108  @param unformatted Base36 string in standard charset encoding
109 
110  @returns Base36 string in custom format
111 
112  @throws InvalidInputStringException
113  """
114  std_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
115  formatted = ""
116 
117  for symbol in unformatted:
118  idx = std_charset.find(symbol)
119 
120  if idx == -1:
122  "Unexpected '%s' in input string." % symbol)
123  else:
124  formatted += self.custom_charsetcustom_charset[idx]
125 
126  return formatted
127 
128  def bytes_to_b36(self, bytes_in):
129  """!
130  Converts bytes to base36 string in custom charset encoding
131 
132  @param bytes_in a bytes object to encode
133 
134  @returns Base36 string in custom format
135  """
136  integer = int.from_bytes(bytes_in, 'big')
137  # convert to base 36
138  if integer < len(self.custom_charsetcustom_charset):
139  return self.custom_charsetcustom_charset[integer]
140  b36string = ""
141  while integer != 0:
142  integer, i = divmod(integer, len(self.custom_charsetcustom_charset))
143  # no need to re-encode this to custom charset as it is already encoded in custom charset
144  b36string = self.custom_charsetcustom_charset[i] + b36string
145  return b36string
146 
147  def int_to_b36(self, integer):
148  """!
149  Converts int to base36 string in custom charset encoding
150 
151  @param integer an int to encode
152 
153  @returns Base36 string in custom format
154 
155  @throws NumberNotPositiveOrZeroException
156  """
157  if integer < 0:
159  "'%s' is not a positive or integer or zero." % integer)
160  else:
161  # convert to base 36
162  if integer < len(self.custom_charsetcustom_charset):
163  return self.custom_charsetcustom_charset[integer]
164  b36string = ""
165  while integer != 0:
166  integer, i = divmod(integer, len(self.custom_charsetcustom_charset))
167  # no need to re-encode this to custom charset as it is already encoded in custom charset
168  b36string = self.custom_charsetcustom_charset[i] + b36string
169  return b36string
170 
171  def b36_to_bytes(self, b36):
172  """!
173  Converts base36 string in custom encoding charset to bytes.
174 
175  @param b36 string in custom encoding charset
176 
177  @returns decoded bytes
178 
179  @throws InvalidInputStringException
180  @throws ValueTooLargeException
181  """
182  integer = self.b36_to_intb36_to_int(b36)
183  length = 1
184  bytesdata = b""
185  while length < 16 and bytesdata == b"":
186  try:
187  bytesdata = integer.to_bytes(length, byteorder='big')
188  break
189  except OverflowError:
190  length += 1
191  if length > 1 and bytesdata == b"":
193  "Value '%s' (%s) is too large to convert to bytes (maximum 16 bytes long integer)" % (b36, integer))
194  return bytesdata
195 
196  def b36_to_int(self, b36):
197  """!
198  Converts base36 string in custom encoding charset to integer.
199 
200  @param b36 base36 string in custom encoding charset
201 
202  @returns decoded integer
203 
204  @throws InvalidInputStringException
205  """
206  # decode from custom charset
207  b36std = self.to_standard_charsetto_standard_charset(b36)
208  # then use normal to_base
209  integer = int(b36std, 36)
210  return integer
This class provides methods allowing conversion between integer, hexadecimal integer and base36 strin...
Definition: base36.py:46
def b36_to_bytes(self, b36)
Converts base36 string in custom encoding charset to bytes.
Definition: base36.py:171
def bytes_to_b36(self, bytes_in)
Converts bytes to base36 string in custom charset encoding.
Definition: base36.py:128
def to_standard_charset(self, unformatted)
Converts custom charset to standard charset.
Definition: base36.py:80
def __init__(self, custom_charset="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
Initialize coder.
Definition: base36.py:54
def int_to_b36(self, integer)
Converts int to base36 string in custom charset encoding.
Definition: base36.py:147
def b36_to_int(self, b36)
Converts base36 string in custom encoding charset to integer.
Definition: base36.py:196
def to_custom_charset(self, unformatted)
Converts standard charset to custom charset.
Definition: base36.py:104
This exception is raised when more than exactly one instance of a given field is contained within fie...
Definition: base36.py:14
This exception is raised when custom character set length .
Definition: base36.py:6
This exception is raised when encountering a character not defined in custom charset in input string.
Definition: base36.py:22
This exception is raised when non-positive integer is passed to encode function.
Definition: base36.py:30
This exception is raised when encountering an integer over maximum size of 16 bytes.
Definition: base36.py:38