This part of the documentation covers the developer interfaces of Shorten.
The base classes used to create and operate stores. Methods that should be implemented by a custom class are indicated.
Stores allow insertion, deletion and lookup of data through an interface similar to a Python dict, the primary difference being that store keys are generated automatically by a key generator (or keygen). tokens are used to delete values from the store and are supplied by a token generator.
Because they are closely associated, keys and tokens are returned in a Pair. A pair is a named tuple containing a key and token (in that order) as well key and token attributes.
s = Store()
key, token = pair = s.insert('aardvark')
# 'aardvark'
s[pair.key]
# True
pair.key == pair[0] == key
# True
pair.token == pair[1] == token
# Removes 'aardvark'
del s[pair.token]
Unlike a Python dict, a BaseStore allows insertion but no modification of its values. Some stores may provide __len__() and __iter__() methods if the underlying storage mechanism makes it feasible.
Subclassing
Subclasses should implement insert(), revoke(), get_value(), has_key(), has_token(), get_token() and get_value()
Parameters: |
|
---|
Get the value for key or default if the key does not exist.
Returns the token for key.
Gets the value for key or raise a KeyError if it doesn’t exist. get() and store[key] will call this method.
Returns True if the key exists in this store, False otherwise.
Returns True if the token exists in this store, False otherwise.
Insert a val and return a Pair, which is a tuple. It contains a key and token (in that order) as well key and token attributes.
pair = store.insert('aardvark')
key, token = pair
# True
pair.key == pair[0] == key
# True
pair.token == pair[1] == token
If the generated key exists or the cannot be stored, a KeyInsertError is raised (or a TokenInsertError for tokens).
try:
store.insert('bonobo')
except (KeyInsertError, TokenInsertError):
print('Cannot insert')
Returns a FormattedPair containing attributes key, token, formatted_key and formatted_token. Calling this method will always consume a key and token.
Revokes the token. A RevokeError is raised if the token is not found or the underlying storage cannot complete the revokation.
try:
store.revoke(token)
print('Revoked!')
except RevokeError:
print('Could not revoke')
A class which yields a unique string on every iteration (a key). If the key generator is deterministic, then two generators should yield the same keys given the same parameters.
alphabet can be any iterable, as long as each item is not contained within any other item. For instance, ('00', '0', '1') would be an ambiguous alphabet, since 00 could be interpreted as two numbers.
Each yielded key is expected to be encoded with encode()
class KeyGenerator(BaseKeyGenerator):
def __iter__(self):
...
yield self.encode(num)
Keys of a minimum length or starting at a certain unencoded value can be generated by specifying min_length or start.
hexabet = '0123456789abcef'
keygen = KeyGenerator(start=255, alphabet=hexabet)
# ['ff', '100', '101']
[key for key in islice(k, 0, 3)]
Subclassing
Subclasses should implement __iter__.
Parameters: |
|
---|
Creates a store with a reasonable keygen.
Deprecated since version 2.0.0: Instantiate stores directly e.g. shorten.MemoryStore(min_length=4)
Stores keys, tokens and data in memory.
If key_gen is None, a MemoryKeygen will be created with the following paramters:
alphabet | an iterable of characters in an alphabet. |
min_length | the minimum key length to begin generating keys at. |
start | the number to start the keygen’s counter at. |
Parameters: | key_gen (a MemoryKeygen or None) – a key generator. If None, a new key generator is created (see above). |
---|
Get the value for key or default if the key does not exist.
Returns a FormattedPair containing attributes key, token, formatted_key and formatted_token. Calling this method will always consume a key and token.
Creates keys in-memory. Keys are always generated in increasing order.
Stores keys, tokens and data in Redis.
If key_gen is None, a RedisKeygen <shorten.RedisKeygen will be created with the following paramters:
alphabet | an iterable of characters in an alphabet. |
min_length | the minimum key length to begin generating keys at. |
start | the number to start the keygen’s counter at. |
counter_key | the Redis key in which to store the keygen’s counter value. |
redis_client | an open Redis connection. |
Parameters: |
|
---|
Inserts a value and returns a Pair.
Key Safety
Keys and tokens are always inserted with a Pipeline, so irrevocable keys will never occur.
If pipe is given, KeyInsertError and TokenInsertError will not be thrown if duplicate keys and tokens exist. Instead, the nth-from-last results must be checked:
pipe = redis.pipeline()
key, token = short.insert('value', pipe)
results = pipe.execute()
if not results[-2]:
raise KeyInsertError(key)
if not results[-1]:
raise TokenInsertError(token)
Attr val: | a value to insert. |
---|---|
Attr pipe: | a Redis pipeline. If None, the pair will be returned immediately. Otherwise they must be extracted from the pipeline results (see above). |
Revokes the key associated with the given revokation token.
If the token does not exist, a KeyError is thrown. Otherwise None is returned.
If pipe is given, then a RevokeError will not be thrown if the key does not exist. The n-th from last result should be checked like so:
pipe = redis.Pipeline()
store.revoke(token, pipe=pipe)
results = pipe.execute()
if not results[-1]:
raise RevokeError(token)
Parameters: | pipe – a Redis pipeline. If None, the token will be revoked immediately. Otherwise they must be extracted from the pipeline results (see above). |
---|
Creates keys in Redis. Keys are always generated in increasing order.
Parameters: |
|
---|
Stores keys, tokens and data in Memcache.
alphabet | an iterable of characters in an alphabet. |
min_length | the minimum key length to begin generating keys at. |
start | the number to start the keygen’s counter at. |
counter_key | the Memcache key in which to store the keygen’s counter value. |
memcache_client | a Memcache client. |
Parameters: |
|
---|
Inserts a value and returns a Pair.
If the generated key exists or memcache cannot store it, a KeyInsertError is raised (or a TokenInsertError if a token exists or cannot be stored).
Creates keys in-memory. Keys are always generated in increasing order.
A token generator which returns the key passed to it.
A token generator which returns a UUID4 (random) token. See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
A formatter is used to format the internal representation of a key or token. This is useful for Redis and SQL databases, which often need to prefix keys and columns in order to avoid clashes.
Subclassing
Subclasses should implement format_key(key) and format_token(token).
Formats a key.
Formats a token.
Prefixes keys and tokens with namespace string.
Parameters: | namespace – a string to prefix to keys and tokens. |
---|
Encodes an integer n in base len(alphabet) with digits in alphabet.
# 'ba'
bx_encode(3, 'abc')
Parameters: |
|
---|
Transforms a string in alphabet to an integer.
If mapping is provided, each key must map to its positional value without duplicates.
mapping = {'a': 0, 'b': 1, 'c': 2}
# 3
bx_decode('ba', 'abc', mapping)
Parameters: |
|
---|