42 lines
1.1 KiB
Python
42 lines
1.1 KiB
Python
# coding: utf-8
|
|
|
|
from __future__ import unicode_literals
|
|
from __future__ import division
|
|
|
|
import math
|
|
from os import urandom
|
|
|
|
|
|
def generate(alphabet='_~0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', size=22):
|
|
"""
|
|
Create a nanoid
|
|
:param alphabet: optional, specify the alphabets for Nano ID generation
|
|
:param size: optional, specify the size of the Nano ID
|
|
:return: Nano ID string
|
|
"""
|
|
if not alphabet:
|
|
return ''
|
|
if size < 1:
|
|
return ''
|
|
masks = [15, 31, 63, 127, 255]
|
|
mask = 1
|
|
for m in masks:
|
|
if m >= len(alphabet) - 1:
|
|
mask = m
|
|
break
|
|
step = int(math.ceil(1.6 * mask * size / len(alphabet)))
|
|
nano_id = ''
|
|
while True:
|
|
random_bytes = bytearray(urandom(step))
|
|
for i in range(step):
|
|
rand_byte = random_bytes[i] & mask
|
|
if rand_byte < len(alphabet):
|
|
if alphabet[rand_byte]:
|
|
nano_id += alphabet[rand_byte]
|
|
if len(nano_id) >= size:
|
|
return nano_id
|
|
|
|
|
|
if __name__ == '__main__':
|
|
print(generate())
|