Encodes a dictionary to an opaque string. :type token: dict :param token: A dictionary containing pagination information, particularly the service pagination token(s) but also other boto metadata. :rtype: str :returns: An opaque string
(self, token)
| 39 | """ |
| 40 | |
| 41 | def encode(self, token): |
| 42 | """Encodes a dictionary to an opaque string. |
| 43 | |
| 44 | :type token: dict |
| 45 | :param token: A dictionary containing pagination information, |
| 46 | particularly the service pagination token(s) but also other boto |
| 47 | metadata. |
| 48 | |
| 49 | :rtype: str |
| 50 | :returns: An opaque string |
| 51 | """ |
| 52 | try: |
| 53 | # Try just using json dumps first to avoid having to traverse |
| 54 | # and encode the dict. In 99.9999% of cases this will work. |
| 55 | json_string = json.dumps(token) |
| 56 | except (TypeError, UnicodeDecodeError): |
| 57 | # If normal dumping failed, go through and base64 encode all bytes. |
| 58 | encoded_token, encoded_keys = self._encode(token, []) |
| 59 | |
| 60 | # Save the list of all the encoded key paths. We can safely |
| 61 | # assume that no service will ever use this key. |
| 62 | encoded_token['boto_encoded_keys'] = encoded_keys |
| 63 | |
| 64 | # Now that the bytes are all encoded, dump the json. |
| 65 | json_string = json.dumps(encoded_token) |
| 66 | |
| 67 | # base64 encode the json string to produce an opaque token string. |
| 68 | return base64.b64encode(json_string.encode('utf-8')).decode('utf-8') |
| 69 | |
| 70 | def _encode(self, data, path): |
| 71 | """Encode bytes in given data, keeping track of the path traversed.""" |