## flexi-human-hash
There are lots of packages that convert big random numbers to something readable or create random strings from words, but none are as flexible as I wanted. I created this to be a highly controllable version of the other human hash packages.
Note that this package is well tested and fairly stable, so don't expect to see many changes unless new GitHub issues are opened.
## Usage
Install:
``` bash
pip install flexi-human-hash
```
Use
``` python
from flexihumanhash import FlexiHumanHash
fhh = FlexiHumanHash("{{adj}}-{{noun}}")
print(fhh.hash("hello world"))
# Expected output: "crookedest-valentines"
print(fhh.hash(42))
# Expected output: "worthiest-omelettes"
print(fhh.hash(bytes([0, 1, 3, 5])))
# Expected output: "manila-dive"
```
## Features:
* Multiple dictionaries: nouns, adjectives, verbs, first name, last name, city
* Full control over formatting: separators, spaces, additional words, upper case, lower case, numbers
* Random: You provide the source of randomness (hash, string, uuid, etc) or one will be provided for you
* Entropy reporting: understand how likely hash collisions are for your given format
* Extendable: add your own dictionaries and formatting transforms
* Jinja2-based templating for more features and control
## API Examples:
Simple hash converted into a string
``` python
fhh = FlexiHumanHash("{{adj}}-{{adj}}-{{noun}}-{{decimal(4)}}")
str(fhh.hash("hello world."))
# Expected output: "manuscript-anatomically-naps-5303"
```
Another format, random number provided for you
``` python
fhh = FlexiHumanHash("{{adj}}, {{adj}} {{noun}} {{hex(4)}}")
print(fhh.rand())
# Expected output: "frolicsome, intelligent mix 89d5"
```
Another format, md5 hash a string for random numbers, transform names to all caps
``` python
fhh = FlexiHumanHash("{{first-name|capitalize}}-{{last-name|capitalize}}-{{decimal(6)}}")
fhh.hash("this is my password...", alg="md5")
# Expected output: "CHARITY-ESMERELDA-903817"
# supported hash algorithms: blake2b (default), blake2s, shake128, shake256, md5, sha1, sha224, sha256, sha384, sha512, sha3-224, sha3-256, sha3-384, sha3-512
```
Report how much entropy is used for a format to help understand likelihood of collisions
``` python
fhh = FlexiHumanHash("{{first-name uppercase}}-{{last-name uppercase}}-{{decimal(6)}}")
print(fhh.entropy)
# Expected output (note BigInt): "70368744177664n"
print(f"Number of combinations: {fhh.entropy:,}")
# Expected output: "Number of combinations: 70,368,744,177,664"
print(f"Entropy: 2^${fhh.entropy_bits}")
# Expected output: "Entropy: 2^46"
```
Add a dictionary from a file
``` python
from pathlib import Path
FlexiTextDict.from_file(Path("./foo.txt")) # file contains one word per line
```
Add a dictionary programmatically
``` python
@register_dict("decimal")
class FlexiDecimalDict(FlexiDict):
def __init__(self, size: int = 4) -> None:
self.sz = size
def get_entry(self, n: int) -> str:
return f"{n:0{self.sz}d}"
@property
def size(self) -> int:
ret: int = 10 ** self.sz
return ret
def preprocess(self, args: tuple[Any, ...], kwargs: dict[str, Any]) -> FlexiDecimalDict:
# this gets called if parameters are passed in to Jinja
return FlexiDecimalDict(*args, **kwargs)
```
## Formats
* noun
* 47,004 English nouns from [categorized-words](https://github.com/felixfischer/categorized-words)
* verb
* 31,232 English verbs from [categorized-words](https://github.com/felixfischer/categorized-words)
* adjective
* 14,903 English adjectives from [categorized-words](https://github.com/felixfischer/categorized-words)
* decimal
* A decimal number (zero through 10), defaults to four digits long but can be a specified number of digits long
* {{decimal}} = 2394
* {{decimal(8)}} = 84258973
* {{decimal(1)}} = 7
* hex
* A hexidecimal number (zero through f), defaults to four nibbles / characters long but can be a specified number of digits long
* {{hex}} = 3fa8
* {{hex(8)}} = cb28f30d
* {{hex(1)}} = e
* femalename
* 4,951 English capitalized female first names / given names from [@stdlib](https://github.com/stdlib-js/datasets-female-first-names-en)
* malename
* 3,898 English capitalized male first names / given names from [@stdlib](https://github.com/stdlib-js/datasets-male-first-names-en)
* firstname
* 8,849 English capitalized first names / given names (female-name and male-name combined)
* lastname
* 21,985 last names / family names from [uuid-readable](https://github.com/Debdut/uuid-readable)
* city
* 138,398 city names from [all-the-cities](https://www.npmjs.com/package/all-the-cities)
## Transforms
* uppercase
* Converts the first letter of a word to uppercase
* e.g. "{{noun|upper}}" -> "Word"
* lowercase
* Converts an entire word to lowercase
* e.g. "{{noun|lower}}" -> "word"
* caps
* Converts an entire word to uppercase
* e.g. "{{noun|capitalize}}" -> "WORD"
Issues and pull requests always welcome, even if you're just saying hi. :)
Thank you to [@stdlib](https://www.npmjs.com/package/@stdlib/stdlib),
[categorized-words](https://www.npmjs.com/package/categorized-words),
[all-the-cities](https://www.npmjs.com/package/all-the-cities), and
[uuid-readable](https://www.npmjs.com/package/uuid-readable) for their word lists.
Raw data
{
"_id": null,
"home_page": "https://github.com/apowers313/pyFlexiHumanHash",
"name": "flexihumanhash",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "hash, human, cryptography, template, md5, sha256",
"author": "Adam Powers",
"author_email": "apowers@ato.ms",
"download_url": "https://files.pythonhosted.org/packages/64/4c/fc2163bf323408d7a2e77303da5f75a905510d1dab08f4a9e6bdca2f3f63/flexihumanhash-0.9.3.tar.gz",
"platform": null,
"description": "## flexi-human-hash\nThere are lots of packages that convert big random numbers to something readable or create random strings from words, but none are as flexible as I wanted. I created this to be a highly controllable version of the other human hash packages.\n\nNote that this package is well tested and fairly stable, so don't expect to see many changes unless new GitHub issues are opened.\n\n## Usage\nInstall:\n``` bash\npip install flexi-human-hash\n```\n\nUse\n``` python\nfrom flexihumanhash import FlexiHumanHash\nfhh = FlexiHumanHash(\"{{adj}}-{{noun}}\")\nprint(fhh.hash(\"hello world\"))\n# Expected output: \"crookedest-valentines\"\nprint(fhh.hash(42))\n# Expected output: \"worthiest-omelettes\"\nprint(fhh.hash(bytes([0, 1, 3, 5])))\n# Expected output: \"manila-dive\"\n```\n\n## Features:\n* Multiple dictionaries: nouns, adjectives, verbs, first name, last name, city\n* Full control over formatting: separators, spaces, additional words, upper case, lower case, numbers\n* Random: You provide the source of randomness (hash, string, uuid, etc) or one will be provided for you\n* Entropy reporting: understand how likely hash collisions are for your given format\n* Extendable: add your own dictionaries and formatting transforms\n* Jinja2-based templating for more features and control\n\n## API Examples:\nSimple hash converted into a string\n``` python\nfhh = FlexiHumanHash(\"{{adj}}-{{adj}}-{{noun}}-{{decimal(4)}}\")\nstr(fhh.hash(\"hello world.\"))\n# Expected output: \"manuscript-anatomically-naps-5303\"\n```\n\nAnother format, random number provided for you\n``` python\nfhh = FlexiHumanHash(\"{{adj}}, {{adj}} {{noun}} {{hex(4)}}\")\nprint(fhh.rand())\n# Expected output: \"frolicsome, intelligent mix 89d5\"\n```\n\nAnother format, md5 hash a string for random numbers, transform names to all caps\n``` python\nfhh = FlexiHumanHash(\"{{first-name|capitalize}}-{{last-name|capitalize}}-{{decimal(6)}}\")\nfhh.hash(\"this is my password...\", alg=\"md5\")\n# Expected output: \"CHARITY-ESMERELDA-903817\"\n# supported hash algorithms: blake2b (default), blake2s, shake128, shake256, md5, sha1, sha224, sha256, sha384, sha512, sha3-224, sha3-256, sha3-384, sha3-512\n```\n\nReport how much entropy is used for a format to help understand likelihood of collisions\n``` python\nfhh = FlexiHumanHash(\"{{first-name uppercase}}-{{last-name uppercase}}-{{decimal(6)}}\")\nprint(fhh.entropy)\n# Expected output (note BigInt): \"70368744177664n\"\nprint(f\"Number of combinations: {fhh.entropy:,}\")\n# Expected output: \"Number of combinations: 70,368,744,177,664\"\nprint(f\"Entropy: 2^${fhh.entropy_bits}\")\n# Expected output: \"Entropy: 2^46\"\n```\n\nAdd a dictionary from a file\n``` python\nfrom pathlib import Path\n\nFlexiTextDict.from_file(Path(\"./foo.txt\")) # file contains one word per line\n```\n\nAdd a dictionary programmatically\n``` python\n@register_dict(\"decimal\")\nclass FlexiDecimalDict(FlexiDict):\n def __init__(self, size: int = 4) -> None:\n self.sz = size\n\n def get_entry(self, n: int) -> str:\n return f\"{n:0{self.sz}d}\" \n\n @property\n def size(self) -> int:\n ret: int = 10 ** self.sz\n return ret\n\n def preprocess(self, args: tuple[Any, ...], kwargs: dict[str, Any]) -> FlexiDecimalDict:\n # this gets called if parameters are passed in to Jinja\n return FlexiDecimalDict(*args, **kwargs)\n```\n\n## Formats\n* noun\n * 47,004 English nouns from [categorized-words](https://github.com/felixfischer/categorized-words)\n* verb\n * 31,232 English verbs from [categorized-words](https://github.com/felixfischer/categorized-words)\n* adjective\n * 14,903 English adjectives from [categorized-words](https://github.com/felixfischer/categorized-words)\n* decimal\n * A decimal number (zero through 10), defaults to four digits long but can be a specified number of digits long\n * {{decimal}} = 2394\n * {{decimal(8)}} = 84258973\n * {{decimal(1)}} = 7\n* hex\n * A hexidecimal number (zero through f), defaults to four nibbles / characters long but can be a specified number of digits long\n * {{hex}} = 3fa8\n * {{hex(8)}} = cb28f30d\n * {{hex(1)}} = e\n* femalename\n * 4,951 English capitalized female first names / given names from [@stdlib](https://github.com/stdlib-js/datasets-female-first-names-en)\n* malename\n * 3,898 English capitalized male first names / given names from [@stdlib](https://github.com/stdlib-js/datasets-male-first-names-en)\n* firstname\n * 8,849 English capitalized first names / given names (female-name and male-name combined)\n* lastname\n * 21,985 last names / family names from [uuid-readable](https://github.com/Debdut/uuid-readable)\n* city\n * 138,398 city names from [all-the-cities](https://www.npmjs.com/package/all-the-cities)\n\n## Transforms\n\n* uppercase\n * Converts the first letter of a word to uppercase\n * e.g. \"{{noun|upper}}\" -> \"Word\"\n* lowercase\n * Converts an entire word to lowercase\n * e.g. \"{{noun|lower}}\" -> \"word\"\n* caps\n * Converts an entire word to uppercase\n * e.g. \"{{noun|capitalize}}\" -> \"WORD\"\n\nIssues and pull requests always welcome, even if you're just saying hi. :)\n\n\nThank you to [@stdlib](https://www.npmjs.com/package/@stdlib/stdlib),\n[categorized-words](https://www.npmjs.com/package/categorized-words),\n[all-the-cities](https://www.npmjs.com/package/all-the-cities), and\n[uuid-readable](https://www.npmjs.com/package/uuid-readable) for their word lists.",
"bugtrack_url": null,
"license": "MIT",
"summary": "Makes hashes readable by humans and gives the developer control over how the output looks.",
"version": "0.9.3",
"project_urls": {
"Homepage": "https://github.com/apowers313/pyFlexiHumanHash",
"Repository": "https://github.com/apowers313/pyFlexiHumanHash"
},
"split_keywords": [
"hash",
" human",
" cryptography",
" template",
" md5",
" sha256"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f5f5670dcb202b7a8235b8b7ceddc89b2b6f22ce68cf63385b29dbe17523b83b",
"md5": "782fd80b3e0e4a0771618b01bdedb422",
"sha256": "3fd76afc8b9cccfe097494949c37263b894608e00978de4d5a6aae3d749f6370"
},
"downloads": -1,
"filename": "flexihumanhash-0.9.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "782fd80b3e0e4a0771618b01bdedb422",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 978227,
"upload_time": "2024-12-25T23:27:55",
"upload_time_iso_8601": "2024-12-25T23:27:55.217144Z",
"url": "https://files.pythonhosted.org/packages/f5/f5/670dcb202b7a8235b8b7ceddc89b2b6f22ce68cf63385b29dbe17523b83b/flexihumanhash-0.9.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "644cfc2163bf323408d7a2e77303da5f75a905510d1dab08f4a9e6bdca2f3f63",
"md5": "f7ce0d080b421d7b4dd40c598238ff3e",
"sha256": "02f458dee203f3daabdf0eb3f6ad4d28a697f8899add47483e7d6e8c2aaf901f"
},
"downloads": -1,
"filename": "flexihumanhash-0.9.3.tar.gz",
"has_sig": false,
"md5_digest": "f7ce0d080b421d7b4dd40c598238ff3e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 981853,
"upload_time": "2024-12-25T23:27:58",
"upload_time_iso_8601": "2024-12-25T23:27:58.254491Z",
"url": "https://files.pythonhosted.org/packages/64/4c/fc2163bf323408d7a2e77303da5f75a905510d1dab08f4a9e6bdca2f3f63/flexihumanhash-0.9.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-25 23:27:58",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "apowers313",
"github_project": "pyFlexiHumanHash",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "flexihumanhash"
}