Skip to content

Instantly share code, notes, and snippets.

@risent
Last active December 11, 2021 10:30
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save risent/4cab3878d995bec7d1c2 to your computer and use it in GitHub Desktop.
Save risent/4cab3878d995bec7d1c2 to your computer and use it in GitHub Desktop.
import random
import time
import numpy
from exceptions import ValueError
class PushID(object):
# Modeled after base64 web-safe chars, but ordered by ASCII.
PUSH_CHARS = ('-0123456789'
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'_abcdefghijklmnopqrstuvwxyz')
def __init__(self):
# Timestamp of last push, used to prevent local collisions if you
# pushtwice in one ms.
self.lastPushTime = 0
# We generate 72-bits of randomness which get turned into 12
# characters and appended to the timestamp to prevent
# collisions with other clients. We store the last characters
# we generated because in the event of a collision, we'll use
# those same characters except "incremented" by one.
self.lastRandChars = numpy.empty(12, dtype=int)
def next_id(self):
now = int(time.time() * 1000)
duplicateTime = (now == self.lastPushTime)
self.lastPushTime = now
timeStampChars = numpy.empty(8, dtype=str)
for i in range(7, -1, -1):
timeStampChars[i] = self.PUSH_CHARS[now % 64]
now = int(now / 64)
if (now != 0):
raise ValueError('We should have converted the entire timestamp.')
uid = ''.join(timeStampChars)
if not duplicateTime:
for i in range(12):
self.lastRandChars[i] = int(random.random() * 64)
else:
# If the timestamp hasn't changed since last push, use the
# same random number, except incremented by 1.
for i in range(11, -1, -1):
if self.lastRandChars[i] == 63:
self.lastRandChars[i] = 0
else:
break
self.lastRandChars[i] += 1
for i in range(12):
uid += self.PUSH_CHARS[self.lastRandChars[i]]
if len(uid) != 20:
raise ValueError('Length should be 20.')
return uid
@LarryWachira
Copy link

LarryWachira commented Aug 22, 2017

Great job on the python port @risent! Why is the else here necessary though?

Edit: Figured it out. Again, thanks for this!

@cmubeenali
Copy link

thank you very much...i was in confusion.

@williamgoodhew
Copy link

thank you for the python script @risent. I am very new to python and I can't seem to call the PushID class correctly.

I am trying to generate a UID for each row in 'full_results_date.csv' and re-write the rows to a new csv 'results_uid.csv' with the uid of each row appended in the new column.

I have added the following code below your script.

`with open('full_results_date.csv', 'r') as csvinput:
with open('results_uid.csv', 'w') as csvoutput:
writer = csv.writer(csvoutput, lineterminator='\n')
reader = csv.reader(csvinput)

    all = []
    row = next(reader)
    row.append(PushID())
    all.append(row)

    for row in reader:
        row.append(PushID())
        all.append(row)

    writer.writerows(all)`

the 'results_uid.csv' has a column appended but each cell in the column is not a UID. Instead, the object location is being returned -
<main.PushID object at 0x109727518>

@jesusignazio
Copy link

Thanks man. It was very helpful

@benfoley
Copy link

benfoley commented Jul 8, 2020

import firebase_pushid

print(firebase_pushid.PushID().next_id())

@jmnguye
Copy link

jmnguye commented Dec 11, 2021

had to remove line 4 to have it work on python 3.8.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment