Giter Club home page Giter Club logo

hashids-python's Introduction

hashids for Python 2.7 & 3

A python port of the JavaScript hashids implementation. It generates YouTube-like hashes from one or many numbers. Use hashids when you do not want to expose your database ids to the user. Website: http://www.hashids.org/

Compatibility

hashids is tested with python 2.7 and 3.5–3.8. PyPy and PyPy 3 work as well.

https://travis-ci.org/davidaurelio/hashids-python.svg?branch=master

Compatibility with the JavaScript implementation

hashids/JavaScript hashids/Python
v0.1.x v0.8.x
v0.3.x+ v1.0.2+

The JavaScript implementation produces different hashes in versions 0.1.x and 0.3.x. For compatibility with the older 0.1.x version install hashids 0.8.4 from pip, otherwise the newest hashids.

Installation

Install the module from PyPI, e. g. with pip:

pip install hashids
pip install hashids==0.8.4 # for compatibility with hashids.js 0.1.x

Run the tests

The tests are written with pytest. The pytest module has to be installed.

python -m pytest

Usage

Import the constructor from the hashids module:

from hashids import Hashids
hashids = Hashids()

Basic Usage

Encode a single integer:

hashid = hashids.encode(123) # 'Mj3'

Decode a hash:

ints = hashids.decode('xoz') # (456,)

To encode several integers, pass them all at once:

hashid = hashids.encode(123, 456, 789) # 'El3fkRIo3'

Decoding is done the same way:

ints = hashids.decode('1B8UvJfXm') # (517, 729, 185)

Using A Custom Salt

Hashids supports salting hashes by accepting a salt value. If you don’t want others to decode your hashes, provide a unique string to the constructor.

hashids = Hashids(salt='this is my salt 1')
hashid = hashids.encode(123) # 'nVB'

The generated hash changes whenever the salt is changed:

hashids = Hashids(salt='this is my salt 2')
hashid = hashids.encode(123) # 'ojK'

A salt string between 6 and 32 characters provides decent randomization.

Controlling Hash Length

By default, hashes are going to be the shortest possible. One reason you might want to increase the hash length is to obfuscate how large the integer behind the hash is.

This is done by passing the minimum hash length to the constructor. Hashes are padded with extra characters to make them seem longer.

hashids = Hashids(min_length=16)
hashid = hashids.encode(1) # '4q2VolejRejNmGQB'

Using A Custom Alphabet

It’s possible to set a custom alphabet for your hashes. The default alphabet is 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'.

To have only lowercase letters in your hashes, pass in the following custom alphabet:

hashids = Hashids(alphabet='abcdefghijklmnopqrstuvwxyz')
hashid = hashids.encode(123456789) # 'kekmyzyk'

A custom alphabet must contain at least 16 characters.

Randomness

The primary purpose of hashids is to obfuscate ids. It's not meant or tested to be used for security purposes or compression. Having said that, this algorithm does try to make these hashes unguessable and unpredictable:

Repeating numbers

There are no repeating patterns that might show that there are 4 identical numbers in the hash:

hashids = Hashids("this is my salt")
hashids.encode(5, 5, 5, 5) # '1Wc8cwcE'

The same is valid for incremented numbers:

hashids.encode(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) # 'kRHnurhptKcjIDTWC3sx'

hashids.encode(1) # 'NV'
hashids.encode(2) # '6m'
hashids.encode(3) # 'yD'
hashids.encode(4) # '2l'
hashids.encode(5) # 'rD'

Curses! #$%@

This code was written with the intent of placing generated hashes in visible places – like the URL. Which makes it unfortunate if generated hashes accidentally formed a bad word.

Therefore, the algorithm tries to avoid generating most common English curse words by never placing the following letters next to each other: c, C, s, S, f, F, h, H, u, U, i, I, t, T.

License

MIT license, see the LICENSE file. You can use hashids in open source projects and commercial products.

hashids-python's People

Contributors

davidaurelio avatar edwardbetts avatar merwok avatar sanketsaurav avatar sg5 avatar titusz avatar vlastv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hashids-python's Issues

How to make HashIds case insensitive?

I want to use HashId for a code that customer must use it and I want to make it case insensitive to make it easy for customer.
Now I use .lower() function and set lower case chars for its alphabet but I'll be glad if I know a cleaner shortcut.

Salt Only uses first 43 Characters

I'm seeing that the salt is limited in usable length (contrary to popular assumptions that you should use a "long random string"). For example, here's a session:

>>> from hashids import Hashids
>>> Hashids('12345678901234567890123456789012345678901234').encode(1)
'WJ'
>>> Hashids('1234567890123456789012345678901234567890123').encode(1)
'WJ'
>>> Hashids('123456789012345678901234567890123456789012').encode(1)
'QN'

It doesn't seem to matter what the contents of the salt are, it's always 43 characters.

I can't immediately see the cause of this - it may be something to do with the length of the alphabet (62) minus the length of the separators (14) and something else. It doesn't seem to be dependent on the length of the number encoded (I tried 8, 16,32,64 and 128 bit numbers).

I'm not sure if this is a bug, an undocumented feature or my (mis)understanding, but thought it worth raising as consumers of this library do indeed recommend "a long and secure salt value...". If it is an undocumented feature, some explanation of why 43 characters would probably be helpful.

(edit: By chance, this also happens to be issue #43 :-) )

Doesn't possible to serialize Hashids-obj

Seems like it doesn't possible to serialize Hashids-obj:

from hashids import Hashids
import pickle
h = Hashids()
h
<hashids.Hashids object at 0x7faccd8097f0>
pickle.dumps(h)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_pickle.PicklingError: Can't pickle <function Hashids.decode at 0x7faccf256e18>: it's not the same object as hashids.Hashids.decode

Count of ids estimation

Hello devs,
Thank you very much for awesome library.
Could you please help me to estimate count of ids based of characters limit.
For example,
6 character long id with alphabet of X chars will provide Y of unique ids
I've tried to calculate via simple <alphabet length>^<length of id> as it would work with baseX algorithm. But this is not the case.

Please help

Array List or Tuple of integer is not supported

Seems like hashids.encode did not accept Array or Tuple argument. while the site said it could convert array of numbers like [27, 986] into “3kTMd”.

it work if hashids.encode(1,2,3),
but if i pass in array like hashids.encode([1,2,3])
it will return
TypeError: int() argument must be a string, a bytes-like object or a number, not 'tuple' / 'list'

this is not an issue if using hashids.js

it could be simply fix by adding another IF to check the values is list or not in line 226

Thanks!

pip and 1.0.0

1.0.0 version is not available through the installer pip

module 'hashids' has no attribute 'encode' - Python 3.6.3

Hi,
I found this interesting but testing on Python 3.6.3 result to error below.

> cd /tmp
> python3 -m venv env
> . env/bin/activate
(env) > pip install hashids
Collecting hashids
  Using cached hashids-1.2.0.tar.gz
Installing collected packages: hashids
  Running setup.py install for hashids ... done
Successfully installed hashids-1.2.0

(env) > python
Python 3.6.3 (default, Oct  4 2017, 06:09:15) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import hashids
>>>
>>> hashid = hashids.encode(123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'hashids' has no attribute 'encode'
>>>
>>> ints = hashids.decode('xoz')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'hashids' has no attribute 'decode'
>>>

Any idea on how to resolve this? Thanks in advance.

Introducing futures/1.0.2 is not a bugfix release

Hey,

we just upgraded from 1.0.1 to 1.0.2, and ran into this bug with New Relic.

`AttributeError: HTTPSConnection instance has no attribute '_nr_external_tracer'

Arguably, introducing the future-dependency was not a bugfix change, since it must be expected to change other code in a non-backwards-compatible manner.

I know you can't do anything about this anymore, since 1.0.2 is published, but I thought I'd document it for others to find. :)

Cheers,
murat

Decode only value

Get the result, without parentheses

ints = hashids.decode('xoz')

Expected result:
456
instead of:
(456,)

1.3.0 release breaks 1.2.0?

I am trying to install hashids 1.2.0, which has worked for a long, long time. This currently fails under a python 3.7.7 venv. Is it possible your 1.3.0 release has affected the previous release of 1.2.0 somehow, e.g. with Flitch?

pip install hashids==1.2.0  
Collecting hashids==1.2.0
ERROR: Package 'hashids' requires a different Python: 3.7.7 not in '~=2.7,~=3.5'

7940cf6#diff-522adf759addbd3b193c74ca85243f7dR21

What is the status of this project?

The last stable release is nearing three years old, and while that does not mean this project is dead, I have to wonder if the library is still reasonably on par with the JS implementation. As it is, the library is good enough for my use case, but it might not be for others, so it might be a good idea to make some updates and to prepare a new release if necessary.

I currently cannot help out much in that front, but I am willing to give some time to update this library's test suite. Adding property-based tests using hypothesis will be a huge improvement in my opinion. Thoughts?

How to use numbers only in alphabet

I use

hashids = Hashids(salt="hello", min_length=6, alphabet='0123456789')

But "Alphabet must contain at least 16 unique characters." execption raised.

Why Alphabet must contain at least 16?

Unicode alphabets not supported?

It seems like unicode alphabets are not supported, but perhaps I am doing something wrong? e.g. the following code (Google Cloud Platform environment)...

alphabet = "😀😃😄😁😆😅😂🤣☺️😊😇🙂🙃😉😌😍😘😗😙"
hashids = Hashids(salt='test3', alphabet=alphabet)
hashid = hashids.encode(123, 456, 789)
self.response.write('<p>alphabet:' + alphabet)
self.response.write('<p>hashid:' + hashid)

I get this output (in a browser):

alphabet:😀😃😄😁😆😅😂🤣☺️😊😇🙂🙃😉😌😍😘😗😙
hashid:����↉����

(i.e. I'd expect hashid to be some combination of faces from alphabet, but they are appearing as [mostly] unknown characters.) Any possibility to add support for these funkier alphabets? Thanks!

Two unique IDs convert back to the same integer

Hi there -- I've found a case were two unique ids decode to the same integer.

As far as I can tell this won't cause any problems for me, I'd just like to understand why this is possible and if it's expected. I've tested the opposite direction (running through a integers to a very high value to ensure there are no conflicts when encoding)

Unfortunately, not sure how to reproduce it here without posting what the integers convert to on my side and the salt I use.

Encoding ids from separate entities and avoiding collisions

Hello 👋 ! Great library @davidaurelio, thanks for putting it together :)

I have a question (a little bit conceptual). Let's say you have two entities/models (Cars and Customers, for example) and you want to generate hashids for them. What's the best way to decode a hashed id (for example xd3rpH7vEp) and realize what entity type it is? I have the following Idea:

BASE_SECRET = "AshD(/084138(/%47iasjd"
hasher = Hashids(salt=BASE_SECRET, min_length=10)

# 1 for cars
# 2 for customers
hasher.encode(1, 115)  # 'xd3rpH7vEp'

hasher.decode('xd3rpH7vEp') # (1, 115) it's a car.

Is it correct? I don't know if it could be a collision with this scheme. Thanks very much!

PyPy and PyPy 3 support?

It might help to add a travis build in order to prove that it works with PyPy and other Python versions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.