├── setup.cfg ├── codenamize ├── __init__.py └── codenamize.py ├── .gitignore ├── TODO.txt ├── tests └── stats.py ├── CHANGES.txt ├── LICENSE.txt ├── setup.py └── README.md /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | -------------------------------------------------------------------------------- /codenamize/__init__.py: -------------------------------------------------------------------------------- 1 | from .codenamize import codenamize, codenamize_particles, codenamize_space 2 | 3 | __author__ = 'Jose Juan Montes [@jjmontesl]' 4 | __description__ = 'Generate consistent easier-to-remember codenames from strings and numbers.' 5 | __version__ = '1.2.3' 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | *.so 3 | *.pyc 4 | 5 | *.egg 6 | *.egg-info 7 | /dist 8 | /build 9 | eggs 10 | sdist 11 | develop-eggs 12 | .installed.cfg 13 | /lib 14 | /lib64 15 | 16 | .project 17 | .pydevproject 18 | .settings 19 | 20 | *.sqlite 21 | 22 | 23 | /ROADMAP 24 | /build 25 | 26 | /virtualenv 27 | /env 28 | 29 | *~ 30 | 31 | .pypirc 32 | 33 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | [HEAD] 2 | 3 | * Add command line option to read from standard input. 4 | * Add command line option to take input as numbers. 5 | 6 | * Blog post. 7 | * Add CI (travis?), coverage (coverall?), and PyPI info and site badges to README. 8 | * Add unit tests (using already written tests). 9 | * Added missing doc to functions. 10 | * Add info to README about command line usage. 11 | 12 | -------------------------------------------------------------------------------- /tests/stats.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | from codenamize import codenamize 3 | import random 4 | 5 | counts = defaultdict(lambda: 0) 6 | 7 | for i in range(0, 2760 * 100): 8 | val = random.randint(0, 999999999999) 9 | res = codenamize(val, 1, 3, '', True) 10 | #print "%s %s" % (val, res) 11 | counts[res] = counts[res] + 1 12 | 13 | for k, v in counts.items(): 14 | print("%s %s" % (k, v)) 15 | print("Length: %d (expected 2760)" % (len(counts))) 16 | 17 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | [1.2.3] 2 | 3 | * Fixed --list_algorithms error affecting Python 3. 4 | * Updated docstring text to match current version test results. 5 | * Added default algorithm information to help text. 6 | 7 | [1.2.2] 8 | 9 | * Fixed bug when using command line without parameter -m. 10 | * Complete Python 2 and 3 support (fixed several 2 & 3 bugs). 11 | 12 | [1.2.0] 13 | 14 | * Now supporting Python 3. 15 | * Hashing algorithm now uses a consistent implementation (thanks hcraT). This 16 | breaks compatibility with existing codenames. 17 | 18 | [1.0.1] 19 | 20 | * Refactored into Python package. 21 | 22 | [1.0.0] 23 | 24 | * Initial version as imported from gist. 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015-2021 Jose Juan Montes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # -*- coding: utf-8 -*- 4 | from setuptools import setup 5 | import re 6 | import os 7 | import sys 8 | import codecs 9 | 10 | 11 | name = 'codenamize' 12 | package = 'codenamize' 13 | description = 'Generate consistent easier-to-remember names from strings and numbers' 14 | long_description = 'Codenamize generates consistent easier-to-remember names for strings and numbers. It is a command line tool and Python library that returns consistent codenames for objects, by joining adjectives and words together.' 15 | url = 'http://github.com/jjmontesl/codenamize' 16 | author = 'Jose Juan Montes' 17 | author_email = 'jjmontes@gmail.com' 18 | license = 'MIT' 19 | install_requires = ['six', 'wheel'] 20 | classifiers = [ 21 | 'Development Status :: 5 - Production/Stable', 22 | 'Intended Audience :: Developers', 23 | 'License :: OSI Approved :: MIT License', 24 | 'Operating System :: POSIX', 25 | 'Programming Language :: Python', 26 | 'Programming Language :: Python :: 2.6', 27 | 'Programming Language :: Python :: 2.7', 28 | 'Programming Language :: Python :: 3', 29 | 'Programming Language :: Python :: 3.2', 30 | 'Programming Language :: Python :: 3.3', 31 | 'Programming Language :: Python :: 3.4', 32 | ] 33 | 34 | 35 | def get_version(package): 36 | """ 37 | Return package version as listed in `__version__` in `init.py`. 38 | """ 39 | init_py = codecs.open(os.path.join(package, '__init__.py'), encoding='utf-8').read() 40 | return re.search("^__version__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1) 41 | 42 | 43 | def get_packages(package): 44 | """ 45 | Return root package and all sub-packages. 46 | """ 47 | return [dirpath 48 | for dirpath, dirnames, filenames in os.walk(package) 49 | if os.path.exists(os.path.join(dirpath, '__init__.py'))] 50 | 51 | 52 | def get_package_data(package): 53 | """ 54 | Return all files under the root package, that are not in a 55 | package themselves. 56 | """ 57 | walk = [(dirpath.replace(package + os.sep, '', 1), filenames) 58 | for dirpath, dirnames, filenames in os.walk(package) 59 | if not os.path.exists(os.path.join(dirpath, '__init__.py'))] 60 | 61 | filepaths = [] 62 | for base, filenames in walk: 63 | filepaths.extend([os.path.join(base, filename) 64 | for filename in filenames]) 65 | return {package: filepaths} 66 | 67 | 68 | if sys.argv[-1] == 'publish': 69 | os.system("python setup.py sdist upload") 70 | args = {'version': get_version(package)} 71 | print("You probably want to also tag the version now:") 72 | print(" git tag -a %(version)s -m 'version %(version)s' && git push --tags" % args) 73 | sys.exit() 74 | 75 | 76 | setup( 77 | name=name, 78 | version=get_version(package), 79 | url=url, 80 | license=license, 81 | description=description, 82 | author=author, 83 | author_email=author_email, 84 | packages=get_packages(package), 85 | package_data=get_package_data(package), 86 | install_requires=install_requires, 87 | classifiers=classifiers, 88 | entry_points={'console_scripts': ['codenamize=codenamize.codenamize:main']}, 89 | ) 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Codenamize 2 | ========== 3 | 4 | **Generate consistent easier-to-remember codenames from strings and numbers.** 5 | 6 | 7 | Overview 8 | ======== 9 | 10 | **Codenamize** is a command line tool and Python library that 11 | returns consistent names for objects, by joining 12 | adjectives and words together. These are easier to remember and 13 | write down than pure numbers, and can be used instead or along UUIDs, 14 | GUIDs, hashes (MD5, SHA...), network addresses and other difficult 15 | to remember strings. 16 | 17 | This can be used to replace identifiers or codes when presenting those to users. 18 | As words are easier to identify and remember for humans, this module maps 19 | Python objects to easy to remember words. 20 | 21 | There are also [Ruby](https://github.com/DannyBen/concode), and [JavaScript](https://github.com/stemail23/codenamize-js) ports available. 22 | 23 | How to install 24 | ============== 25 | 26 | 1. easy_install codenamize 27 | 2. pip install codenamize 28 | 3. git clone http://github.com/jjmontesl/codenamize 29 | a. cd codenamize 30 | b. run python setup.py 31 | 4. wget https://github.com/jjmontesl/codenamize/zipball/master 32 | a. unzip the downloaded file 33 | b. cd into codenamize-* directory 34 | c. run python setup.py 35 | 36 | 37 | Usage from Python 38 | ----------------- 39 | 40 | Import the codenamize function: 41 | 42 | >>> from codenamize import codenamize 43 | 44 | Consecutive numbers yield differentiable codenames: 45 | 46 | >>> codenamize("1") 47 | 'familiar-grand' 48 | >>> codenamize("2") 49 | 'little-tip' 50 | 51 | If you later want to add more adjectives, your existing codenames 52 | are retained as suffixes: 53 | 54 | >>> codenamize("11:22:33:44:55:66") 55 | 'craven-delivery' 56 | >>> codenamize("11:22:33:44:55:66", 2) 57 | 'separate-craven-delivery' 58 | 59 | Note that integers are internally converted to strings before hashing: 60 | 61 | >>> codenamize(1) 62 | 'familiar-grand' 63 | 64 | Other options (max characters, join character, capitalize): 65 | 66 | >>> codenamize(0x123456aa, 2, 3, '', True) 67 | 'SadBigFat' 68 | >>> codenamize(0x123456aa, 2, 0, '', True) 69 | 'BrawnyEminentBear' 70 | >>> codenamize(0x123456aa, 5, 0, ' ', True) 71 | 'Spotty Disagreeable Modern Brawny Eminent Bear' 72 | >>> codenamize(0x123456aa, 4, 0, ' ', False) 73 | 'disagreeable modern brawny eminent bear' 74 | 75 | 76 | Usage as command line tool 77 | -------------------------- 78 | 79 | After installing, run `codenamize --help` for help: 80 | 81 | usage: codenamize [-h] [-p PREFIX] [-m MAXCHARS] [-j JOIN] [-c] [--space] 82 | [--tests] [--version] 83 | [strings [strings ...]] 84 | 85 | Generate consistent easier-to-remember codenames from strings and numbers. 86 | 87 | positional arguments: 88 | strings One or more strings to codenamize. 89 | 90 | optional arguments: 91 | -h, --help show this help message and exit 92 | -p PREFIX, --prefix PREFIX 93 | number of prefixes to use 94 | -m MAXCHARS, --maxchars MAXCHARS 95 | max word characters (0 for no limit) 96 | -a HASH_ALGO, --hash_algorithm HASH_ALGO 97 | the algorithm to use to hash the input value 98 | (default: md5) 99 | -j JOIN, --join JOIN separator between words (default: -) 100 | -c, --capitalize capitalize words 101 | --space show codename space for the given arguments 102 | --tests show information and samples 103 | --list_algorithms List the hash algorithms available 104 | --version show program's version number and exit 105 | 106 | 107 | Examples 108 | -------- 109 | 110 | For numbers 100000-100009, show codenames with 0-2 adjectives and different options: 111 | 112 | OBJ ADJ0-MAX5 ADJ1-MAX5 ADJ2-MAX5 ADJ-0, ADJ-1, ADJ-2 (capitalized, empty join character) 113 | 100001 boat funny-boat real-funny-boat Community, RacialCommunity, PluckyRacialCommunity 114 | 100002 award first-award tidy-first-award Repeat, UptightRepeat, HelpfulUptightRepeat 115 | 100003 rush super-rush equal-super-rush Intention, ExpensiveIntention, JazzyExpensiveIntention 116 | 100004 uncle calm-uncle icky-calm-uncle March, SubduedMarch, AdamantSubduedMarch 117 | 100005 salad warm-salad true-warm-salad Plant, QuickestPlant, ReminiscentQuickestPlant 118 | 100006 gift witty-gift odd-witty-gift Estimate, CreepyEstimate, SpectacularCreepyEstimate 119 | 100007 son zany-son gaudy-zany-son Truck, MiniatureTruck, OptimalMiniatureTruck 120 | 100008 angle damp-angle dusty-damp-angle Steak, SpectacularSteak, RightfulSpectacularSteak 121 | 100009 link utter-link null-utter-link Bike, ImportantBike, SweetImportantBike 122 | 123 | 124 | Codename space sizes 125 | -------------------- 126 | 127 | In selecting the number of adjectives and max chars to use, consider how 128 | many codenames you need to fit the number of objects you'll handle, since 129 | the probability of collision increases with the number of different objects 130 | used. 131 | 132 | 0 adj (max 3 chars) = 115 combinations 133 | 0 adj (max 4 chars) = 438 combinations 134 | 0 adj (max 5 chars) = 742 combinations 135 | 0 adj (max 6 chars) = 987 combinations 136 | 0 adj (max 7 chars) = 1176 combinations 137 | 0 adj (max 0 chars) = 1525 combinations 138 | 1 adj (max 3 chars) = 2760 combinations 139 | 1 adj (max 4 chars) = 56940 combinations 140 | 1 adj (max 5 chars) = 241150 combinations 141 | 1 adj (max 6 chars) = 492513 combinations 142 | 1 adj (max 7 chars) = 789096 combinations 143 | 1 adj (max 0 chars) = 1701900 combinations 144 | 2 adj (max 3 chars) = 66240 combinations 145 | 2 adj (max 4 chars) = 7402200 combinations 146 | 2 adj (max 5 chars) = 78373750 combinations 147 | 2 adj (max 6 chars) = 245763987 combinations 148 | 2 adj (max 7 chars) = 529483416 combinations 149 | 2 adj (max 0 chars) = 1899320400 combinations 150 | 151 | An example is shown by running codenamize --tests . 152 | 153 | 154 | Other versions 155 | ============== 156 | 157 | * [Concode](https://github.com/DannyBen/concode) - Ruby port (thanks to Danny Ben Shitrit) 158 | * [Codenamize JS](https://github.com/stemail23/codenamize-js) - JavaScript port (by Steven Barlow) 159 | 160 | 161 | License 162 | ==================== 163 | 164 | Codenamize is released under MIT license. 165 | 166 | For full license see the LICENSE file. 167 | 168 | -------------------------------------------------------------------------------- /codenamize/codenamize.py: -------------------------------------------------------------------------------- 1 | # codenamize module 2 | # Generate consistent easier-to-remember codenames from strings and numbers. 3 | # Jose Juan Montes 2015-2016 - MIT License 4 | import six 5 | 6 | """ 7 | Returns consistent codenames for objects, by joining 8 | adjectives and words together. These are easier to remember and 9 | write down than pure numbers, and can be used instead or along UUIDs, 10 | GUIDs, hashes (MD5, SHA...), network addresses and other difficult 11 | to remember strings. 12 | 13 | This can be used to replace identifiers or codes when presenting those to users. 14 | As words are easier to identify and remember for humans, this module maps 15 | python objects to easy to remember words. 16 | 17 | Usage 18 | ----- 19 | 20 | Import the codenamize function: 21 | 22 | >>> from codenamize import codenamize 23 | 24 | Consecutive numbers yield differentiable codenames: 25 | 26 | >>> codenamize("1") 27 | 'familiar-grand' 28 | >>> codenamize("2") 29 | 'little-tip' 30 | 31 | If you later want to add more adjectives, your existing codenames 32 | are retained as suffixes: 33 | 34 | >>> codenamize("11:22:33:44:55:66") 35 | 'craven-delivery' 36 | >>> codenamize("11:22:33:44:55:66", 2) 37 | 'separate-craven-delivery' 38 | 39 | Integers are internally converted to strings: 40 | 41 | >>> codenamize(1) 42 | 'familiar-grand' 43 | 44 | Other options (max characters, join character, capitalize): 45 | 46 | >>> codenamize(0x123456aa, 2, 3, '', True) 47 | 'SadBigFat' 48 | >>> codenamize(0x123456aa, 2, 0, '', True) 49 | 'BrawnyEminentBear' 50 | >>> codenamize(0x123456aa, 4, 0, ' ', False) 51 | 'disagreeable modern brawny eminent bear' 52 | 53 | 54 | Examples 55 | -------- 56 | 57 | For numbers 100000-100009 show codenames with 0-2 adjectives and different options: 58 | 59 | OBJ ADJ0-MAX5 ADJ1-MAX5 ADJ2-MAX5 ADJ-0, ADJ-1, ADJ-2 (capitalized, empty join character) 60 | 100001 boat funny-boat real-funny-boat Community, RacialCommunity, PluckyRacialCommunity 61 | 100002 award first-award tidy-first-award Repeat, UptightRepeat, HelpfulUptightRepeat 62 | 100003 rush super-rush equal-super-rush Intention, ExpensiveIntention, JazzyExpensiveIntention 63 | 100004 uncle calm-uncle icky-calm-uncle March, SubduedMarch, AdamantSubduedMarch 64 | 100005 salad warm-salad true-warm-salad Plant, QuickestPlant, ReminiscentQuickestPlant 65 | 100006 gift witty-gift odd-witty-gift Estimate, CreepyEstimate, SpectacularCreepyEstimate 66 | 100007 son zany-son gaudy-zany-son Truck, MiniatureTruck, OptimalMiniatureTruck 67 | 100008 angle damp-angle dusty-damp-angle Steak, SpectacularSteak, RightfulSpectacularSteak 68 | 100009 link utter-link null-utter-link Bike, ImportantBike, SweetImportantBike 69 | 70 | Codename space sizes 71 | -------------------- 72 | 73 | In selecting the number of adjectives and max chars to use, consider how 74 | many codenames you need to fit the number of objects you'll handle, since 75 | the probability of collision increases with the number of different objects 76 | used. 77 | 78 | 0 adj (max 3 chars) = 115 combinations 79 | 0 adj (max 4 chars) = 438 combinations 80 | 0 adj (max 5 chars) = 742 combinations 81 | 0 adj (max 6 chars) = 987 combinations 82 | 0 adj (max 7 chars) = 1176 combinations 83 | 0 adj (max 0 chars) = 1525 combinations 84 | 1 adj (max 3 chars) = 2760 combinations 85 | 1 adj (max 4 chars) = 56940 combinations 86 | 1 adj (max 5 chars) = 241150 combinations 87 | 1 adj (max 6 chars) = 492513 combinations 88 | 1 adj (max 7 chars) = 789096 combinations 89 | 1 adj (max 0 chars) = 1701900 combinations 90 | 2 adj (max 3 chars) = 66240 combinations 91 | 2 adj (max 4 chars) = 7402200 combinations 92 | 2 adj (max 5 chars) = 78373750 combinations 93 | 2 adj (max 6 chars) = 245763987 combinations 94 | 2 adj (max 7 chars) = 529483416 combinations 95 | 2 adj (max 0 chars) = 1899320400 combinations 96 | 97 | An example is shown by running codenamize --tests . 98 | """ 99 | 100 | import argparse 101 | import hashlib 102 | import functools 103 | import sys 104 | 105 | ADJECTIVES = [ 106 | "aback","abaft","abandoned","abashed","aberrant","abhorrent","abiding","abject","ablaze","able","abnormal","aboard","aboriginal","abortive","abounding","abrasive","abrupt","absent","absorbed","absorbing","abstracted","absurd","abundant","abusive","acceptable","accessible","accidental","accurate","acid","acidic","acoustic","acrid","actually","ad hoc","adamant","adaptable","addicted","adhesive","adjoining","adorable","adventurous","afraid","aggressive","agonizing","agreeable","ahead","ajar","alcoholic","alert","alike","alive","alleged","alluring","aloof","amazing","ambiguous","ambitious","amuck","amused","amusing","ancient","angry","animated","annoyed","annoying","anxious","apathetic","aquatic","aromatic","arrogant","ashamed","aspiring","assorted","astonishing","attractive","auspicious","automatic","available","average","awake","aware","awesome","awful","axiomatic", 107 | "bad","barbarous","bashful","bawdy","beautiful","befitting","belligerent","beneficial","bent","berserk","best","better","bewildered","big","billowy","bitter","bizarre","black","bloody","blue","blushing","boiling","boorish","bored","boring","bouncy","boundless","brainy","brash","brave","brawny","breakable","breezy","brief","bright","bright","broad","broken","brown","bumpy","burly","bustling","busy", 108 | "cagey","calculating","callous","calm","capable","capricious","careful","careless","caring","cautious","ceaseless","certain","changeable","charming","cheap","cheerful","chemical","chief","childlike","chilly","chivalrous","chubby","chunky","clammy","classy","clean","clear","clever","cloistered","cloudy","closed","clumsy","cluttered","coherent","cold","colorful","colossal","combative","comfortable","common","complete","complex","concerned","condemned","confused","conscious","cooing","cool","cooperative","coordinated","courageous","cowardly","crabby","craven","crazy","creepy","crooked","crowded","cruel","cuddly","cultured","cumbersome","curious","curly","curved","curvy","cut","cute","cute","cynical", 109 | "daffy","daily","damaged","damaging","damp","dangerous","dapper","dark","dashing","dazzling","dead","deadpan","deafening","dear","debonair","decisive","decorous","deep","deeply","defeated","defective","defiant","delicate","delicious","delightful","demonic","delirious","dependent","depressed","deranged","descriptive","deserted","detailed","determined","devilish","didactic","different","difficult","diligent","direful","dirty","disagreeable","disastrous","discreet","disgusted","disgusting","disillusioned","dispensable","distinct","disturbed","divergent","dizzy","domineering","doubtful","drab","draconian","dramatic","dreary","drunk","dry","dull","dusty","dusty","dynamic","dysfunctional", 110 | "eager","early","earsplitting","earthy","easy","eatable","economic","educated","efficacious","efficient","eight","elastic","elated","elderly","electric","elegant","elfin","elite","embarrassed","eminent","empty","enchanted","enchanting","encouraging","endurable","energetic","enormous","entertaining","enthusiastic","envious","equable","equal","erect","erratic","ethereal","evanescent","evasive","even","excellent","excited","exciting","exclusive","exotic","expensive","extra","exuberant","exultant", 111 | "fabulous","faded","faint","fair","faithful","fallacious","false","familiar","famous","fanatical","fancy","fantastic","far","fascinated","fast","fat","faulty","fearful","fearless","feeble","feigned","female","fertile","festive","few","fierce","filthy","fine","finicky","first","five","fixed","flagrant","flaky","flashy","flat","flawless","flimsy","flippant","flowery","fluffy","fluttering","foamy","foolish","foregoing","forgetful","fortunate","four","frail","fragile","frantic","free","freezing","frequent","fresh","fretful","friendly","frightened","frightening","full","fumbling","functional","funny","furry","furtive","future","futuristic","fuzzy", 112 | "gabby","gainful","gamy","gaping","garrulous","gaudy","general","gentle","giant","giddy","gifted","gigantic","glamorous","gleaming","glib","glistening","glorious","glossy","godly","good","goofy","gorgeous","graceful","grandiose","grateful","gratis","gray","greasy","great","greedy","green","grey","grieving","groovy","grotesque","grouchy","grubby","gruesome","grumpy","guarded","guiltless","gullible","gusty","guttural", 113 | "habitual","half","hallowed","halting","handsome","handsomely","handy","hanging","hapless","happy","hard","harmonious","harsh","hateful","heady","healthy","heartbreaking","heavenly","heavy","hellish","helpful","helpless","hesitant","hideous","high","highfalutin","hilarious","hissing","historical","holistic","hollow","homeless","homely","honorable","horrible","hospitable","hot","huge","hulking","humdrum","humorous","hungry","hurried","hurt","hushed","husky","hypnotic","hysterical", 114 | "icky","icy","idiotic","ignorant","ill","illegal","illustrious","imaginary","immense","imminent","impartial","imperfect","impolite","important","imported","impossible","incandescent","incompetent","inconclusive","industrious","incredible","inexpensive","infamous","innate","innocent","inquisitive","insidious","instinctive","intelligent","interesting","internal","invincible","irate","irritating","itchy", 115 | "jaded","jagged","jazzy","jealous","jittery","jobless","jolly","joyous","judicious","juicy","jumbled","jumpy","juvenile", 116 | "kaput","keen","kind","kindhearted","kindly","knotty","knowing","knowledgeable","known", 117 | "labored","lackadaisical","lacking","lame","lamentable","languid","large","last","late","laughable","lavish","lazy","lean","learned","left","legal","lethal","level","lewd","light","like","likeable","limping","literate","little","lively","lively","living","lonely","long","longing","loose","lopsided","loud","loutish","lovely","loving","low","lowly","lucky","ludicrous","lumpy","lush","luxuriant","lying","lyrical", 118 | "macabre","macho","maddening","madly","magenta","magical","magnificent","majestic","makeshift","male","malicious","mammoth","maniacal","many","marked","massive","married","marvelous","material","materialistic","mature","mean","measly","meaty","medical","meek","mellow","melodic","melted","merciful","mere","messy","mighty","military","milky","mindless","miniature","minor","miscreant","misty","mixed","moaning","modern","moldy","momentous","motionless","mountainous","muddled","mundane","murky","mushy","mute","mysterious", 119 | "naive","nappy","narrow","nasty","natural","naughty","nauseating","near","neat","nebulous","necessary","needless","needy","neighborly","nervous","new","next","nice","nifty","nimble","nine","nippy","noiseless","noisy","nonchalant","nondescript","nonstop","normal","nostalgic","nosy","noxious","null","numberless","numerous","nutritious","nutty", 120 | "oafish","obedient","obeisant","obese","obnoxious","obscene","obsequious","observant","obsolete","obtainable","oceanic","odd","offbeat","old","omniscient","one","onerous","open","opposite","optimal","orange","ordinary","organic","ossified","outgoing","outrageous","outstanding","oval","overconfident","overjoyed","overrated","overt","overwrought", 121 | "painful","painstaking","pale","paltry","panicky","panoramic","parallel","parched","parsimonious","past","pastoral","pathetic","peaceful","penitent","perfect","periodic","permissible","perpetual","petite","petite","phobic","physical","picayune","pink","piquant","placid","plain","plant","plastic","plausible","pleasant","plucky","pointless","poised","polite","political","poor","possessive","possible","powerful","precious","premium","present","pretty","previous","pricey","prickly","private","probable","productive","profuse","protective","proud","psychedelic","psychotic","public","puffy","pumped","puny","purple","purring","pushy","puzzled","puzzling", 122 | "quack","quaint","quarrelsome","questionable","quick","quickest","quiet","quirky","quixotic","quizzical", 123 | "rabid","racial","ragged","rainy","rambunctious","rampant","rapid","rare","raspy","ratty","ready","real","rebel","receptive","recondite","red","redundant","reflective","regular","relieved","remarkable","reminiscent","repulsive","resolute","resonant","responsible","rhetorical","rich","right","righteous","rightful","rigid","ripe","ritzy","roasted","robust","romantic","roomy","rotten","rough","round","royal","ruddy","rude","rural","rustic","ruthless", 124 | "sable","sad","safe","salty","same","sassy","satisfying","savory","scandalous","scarce","scared","scary","scattered","scientific","scintillating","scrawny","screeching","second","secret","secretive","sedate","seemly","selective","selfish","separate","serious","shaggy","shaky","shallow","sharp","shiny","shivering","shocking","short","shrill","shut","shy","sick","silent","silent","silky","silly","simple","simplistic","sincere","six","skillful","skinny","sleepy","slim","slimy","slippery","sloppy","slow","small","smart","smelly","smiling","smoggy","smooth","sneaky","snobbish","snotty","soft","soggy","solid","somber","sophisticated","sordid","sore","sore","sour","sparkling","special","spectacular","spicy","spiffy","spiky","spiritual","spiteful","splendid","spooky","spotless","spotted","spotty","spurious","squalid","square","squealing","squeamish","staking","stale","standing","statuesque","steadfast","steady","steep","stereotyped","sticky","stiff","stimulating","stingy","stormy","straight","strange","striped","strong","stupendous","stupid","sturdy","subdued","subsequent","substantial","successful","succinct","sudden","sulky","super","superb","superficial","supreme","swanky","sweet","sweltering","swift","symptomatic","synonymous", 125 | "taboo","tacit","tacky","talented","tall","tame","tan","tangible","tangy","tart","tasteful","tasteless","tasty","tawdry","tearful","tedious","teeny","telling","temporary","ten","tender","tense","tense","tenuous","terrible","terrific","tested","testy","thankful","therapeutic","thick","thin","thinkable","third","thirsty","thirsty","thoughtful","thoughtless","threatening","three","thundering","tidy","tight","tightfisted","tiny","tired","tiresome","toothsome","torpid","tough","towering","tranquil","trashy","tremendous","tricky","trite","troubled","truculent","true","truthful","two","typical", 126 | "ubiquitous","ugliest","ugly","ultra","unable","unaccountable","unadvised","unarmed","unbecoming","unbiased","uncovered","understood","undesirable","unequal","unequaled","uneven","unhealthy","uninterested","unique","unkempt","unknown","unnatural","unruly","unsightly","unsuitable","untidy","unused","unusual","unwieldy","unwritten","upbeat","uppity","upset","uptight","used","useful","useless","utopian","utter","uttermost", 127 | "vacuous","vagabond","vague","valuable","various","vast","vengeful","venomous","verdant","versed","victorious","vigorous","violent","violet","vivacious","voiceless","volatile","voracious","vulgar", 128 | "wacky","waggish","waiting","wakeful","wandering","wanting","warlike","warm","wary","wasteful","watery","weak","wealthy","weary","wet","whimsical","whispering","white","whole","wholesale","wicked","wide","wiggly","wild","willing","windy","wiry","wise","wistful","witty","woebegone","womanly","wonderful","wooden","woozy","workable","worried","worthless","wrathful","wretched","wrong","wry", 129 | "xenophobic","yellow","yielding","young","youthful","yummy","zany","zealous","zesty","zippy","zonked", 130 | ] 131 | 132 | NOUNS = [ 133 | "a","ability","abroad","abuse","access","accident","account","act","action","active","activity","actor","ad","addition","address","administration","adult","advance","advantage","advertising","advice","affair","affect","afternoon","age","agency","agent","agreement","air","airline","airport","alarm","alcohol","alternative","ambition","amount","analysis","analyst","anger","angle","animal","annual","answer","anxiety","anybody","anything","anywhere","apartment","appeal","appearance","apple","application","appointment","area","argument","arm","army","arrival","art","article","aside","ask","aspect","assignment","assist","assistance","assistant","associate","association","assumption","atmosphere","attack","attempt","attention","attitude","audience","author","average","award","awareness", 134 | "baby","back","background","bad","bag","bake","balance","ball","band","bank","bar","base","baseball","basis","basket","bat","bath","bathroom","battle","beach","bear","beat","beautiful","bed","bedroom","beer","beginning","being","bell","belt","bench","bend","benefit","bet","beyond","bicycle","bid","big","bike","bill","bird","birth","birthday","bit","bite","bitter","black","blame","blank","blind","block","blood","blow","blue","board","boat","body","bone","bonus","book","boot","border","boss","bother","bottle","bottom","bowl","box","boy","boyfriend","brain","branch","brave","bread","break","breakfast","breast","breath","brick","bridge","brief","brilliant","broad","brother","brown","brush","buddy","budget","bug","building","bunch","burn","bus","business","button","buy","buyer", 135 | "cabinet","cable","cake","calendar","call","calm","camera","camp","campaign","can","cancel","cancer","candidate","candle","candy","cap","capital","car","card","care","career","carpet","carry","case","cash","cat","catch","category","cause","celebration","cell","chain","chair","challenge","champion","championship","chance","change","channel","chapter","character","charge","charity","chart","check","cheek","chemical","chemistry","chest","chicken","child","childhood","chip","chocolate","choice","church","cigarette","city","claim","class","classic","classroom","clerk","click","client","climate","clock","closet","clothes","cloud","club","clue","coach","coast","coat","code","coffee","cold","collar","collection","college","combination","combine","comfort","comfortable","command","comment","commercial","commission","committee","common","communication","community","company","comparison","competition","complaint","complex","computer","concentrate","concept","concern","concert","conclusion","condition","conference","confidence","conflict","confusion","connection","consequence","consideration","consist","constant","construction","contact","contest","context","contract","contribution","control","conversation","convert","cook","cookie","copy","corner","cost","count","counter","country","county","couple","courage","course","court","cousin","cover","cow","crack","craft","crash","crazy","cream","creative","credit","crew","criticism","cross","cry","culture","cup","currency","current","curve","customer","cut","cycle", 136 | "dad","damage","dance","dare","dark","data","database","date","daughter","day","dead","deal","dealer","dear","death","debate","debt","decision","deep","definition","degree","delay","delivery","demand","department","departure","dependent","deposit","depression","depth","description","design","designer","desire","desk","detail","development","device","devil","diamond","diet","difference","difficulty","dig","dimension","dinner","direction","director","dirt","disaster","discipline","discount","discussion","disease","dish","disk","display","distance","distribution","district","divide","doctor","document","dog","door","dot","double","doubt","draft","drag","drama","draw","drawer","drawing","dream","dress","drink","drive","driver","drop","drunk","due","dump","dust","duty", 137 | "ear","earth","ease","east","eat","economics","economy","edge","editor","education","effect","effective","efficiency","effort","egg","election","elevator","emergency","emotion","emphasis","employ","employee","employer","employment","end","energy","engine","engineer","engineering","entertainment","enthusiasm","entrance","entry","environment","equal","equipment","equivalent","error","escape","essay","establishment","estate","estimate","evening","event","evidence","exam","examination","example","exchange","excitement","excuse","exercise","exit","experience","expert","explanation","expression","extension","extent","external","extreme","eye", 138 | "face","fact","factor","fail","failure","fall","familiar","family","fan","farm","farmer","fat","father","fault","fear","feature","fee","feed","feedback","feel","feeling","female","few","field","fight","figure","file","fill","film","final","finance","finding","finger","finish","fire","fish","fishing","fix","flight","floor","flow","flower","fly","focus","fold","following","food","foot","football","force","forever","form","formal","fortune","foundation","frame","freedom","friend","friendship","front","fruit","fuel","fun","function","funeral","funny","future", 139 | "gain","game","gap","garage","garbage","garden","gas","gate","gather","gear","gene","general","gift","girl","girlfriend","give","glad","glass","glove","go","goal","god","gold","golf","good","government","grab","grade","grand","grandfather","grandmother","grass","great","green","grocery","ground","group","growth","guarantee","guard","guess","guest","guidance","guide","guitar","guy", 140 | "habit","hair","half","hall","hand","handle","hang","harm","hat","hate","head","health","hearing","heart","heat","heavy","height","hell","hello","help","hide","high","highlight","highway","hire","historian","history","hit","hold","hole","holiday","home","homework","honey","hook","hope","horror","horse","hospital","host","hotel","hour","house","housing","human","hunt","hurry","hurt","husband", 141 | "ice","idea","ideal","if","illegal","image","imagination","impact","implement","importance","impress","impression","improvement","incident","income","increase","independence","independent","indication","individual","industry","inevitable","inflation","influence","information","initial","initiative","injury","insect","inside","inspection","inspector","instance","instruction","insurance","intention","interaction","interest","internal","international","internet","interview","introduction","investment","invite","iron","island","issue","it","item", 142 | "jacket","job","join","joint","joke","judge","judgment","juice","jump","junior","jury", 143 | "keep","key","kick","kid","kill","kind","king","kiss","kitchen","knee","knife","knowledge", 144 | "lab","lack","ladder","lady","lake","land","landscape","language","laugh","law","lawyer","lay","layer","lead","leader","leadership","leading","league","leather","leave","lecture","leg","length","lesson","let","letter","level","library","lie","life","lift","light","limit","line","link","lip","list","listen","literature","living","load","loan","local","location","lock","log","long","look","loss","love","low","luck","lunch", 145 | "machine","magazine","mail","main","maintenance","major","make","male","mall","man","management","manager","manner","manufacturer","many","map","march","mark","market","marketing","marriage","master","match","mate","material","math","matter","maximum","maybe","meal","meaning","measurement","meat","media","medicine","medium","meet","meeting","member","membership","memory","mention","menu","mess","message","metal","method","middle","midnight","might","milk","mind","mine","minimum","minor","minute","mirror","miss","mission","mistake","mix","mixture","mobile","mode","model","mom","moment","money","monitor","month","mood","morning","mortgage","most","mother","motor","mountain","mouse","mouth","move","movie","mud","muscle","music", 146 | "nail","name","nasty","nation","national","native","natural","nature","neat","necessary","neck","negative","negotiation","nerve","net","network","news","newspaper","night","nobody","noise","normal","north","nose","note","nothing","notice","novel","number","nurse", 147 | "object","objective","obligation","occasion","offer","office","officer","official","oil","one","opening","operation","opinion","opportunity","opposite","option","orange","order","ordinary","organization","original","other","outcome","outside","oven","owner", 148 | "pace","pack","package","page","pain","paint","painting","pair","panic","paper","parent","park","parking","part","particular","partner","party","pass","passage","passenger","passion","past","path","patience","patient","pattern","pause","pay","payment","peace","peak","pen","penalty","pension","people","percentage","perception","performance","period","permission","permit","person","personal","personality","perspective","phase","philosophy","phone","photo","phrase","physical","physics","piano","pick","picture","pie","piece","pin","pipe","pitch","pizza","place","plan","plane","plant","plastic","plate","platform","play","player","pleasure","plenty","poem","poet","poetry","point","police","policy","politics","pollution","pool","pop","population","position","positive","possession","possibility","possible","post","pot","potato","potential","pound","power","practice","preference","preparation","presence","present","presentation","president","press","pressure","price","pride","priest","primary","principle","print","prior","priority","private","prize","problem","procedure","process","produce","product","profession","professional","professor","profile","profit","program","progress","project","promise","promotion","prompt","proof","property","proposal","protection","psychology","public","pull","punch","purchase","purple","purpose","push","put", 149 | "quality","quantity","quarter","queen","question","quiet","quit","quote", 150 | "race","radio","rain","raise","range","rate","ratio","raw","reach","reaction","read","reading","reality","reason","reception","recipe","recognition","recommendation","record","recording","recover","red","reference","reflection","refrigerator","refuse","region","register","regret","regular","relation","relationship","relative","release","relief","remote","remove","rent","repair","repeat","replacement","reply","report","representative","republic","reputation","request","requirement","research","reserve","resident","resist","resolution","resolve","resort","resource","respect","respond","response","responsibility","rest","restaurant","result","return","reveal","revenue","review","revolution","reward","rice","rich","ride","ring","rip","rise","risk","river","road","rock","role","roll","roof","room","rope","rough","round","routine","row","royal","rub","ruin","rule","run","rush", 151 | "sad","safe","safety","sail","salad","salary","sale","salt","sample","sand","sandwich","satisfaction","save","savings","scale","scene","schedule","scheme","school","science","score","scratch","screen","screw","script","sea","search","season","seat","second","secret","secretary","section","sector","security","selection","self","sell","senior","sense","sensitive","sentence","series","serve","service","session","set","setting","sex","shake","shame","shape","share","she","shelter","shift","shine","ship","shirt","shock","shoe","shoot","shop","shopping","shot","shoulder","show","shower","sick","side","sign","signal","signature","significance","silly","silver","simple","sing","singer","single","sink","sir","sister","site","situation","size","skill","skin","skirt","sky","sleep","slice","slide","slip","smell","smile","smoke","snow","society","sock","soft","software","soil","solid","solution","somewhere","son","song","sort","sound","soup","source","south","space","spare","speaker","special","specialist","specific","speech","speed","spell","spend","spirit","spiritual","spite","split","sport","spot","spray","spread","spring","square","stable","staff","stage","stand","standard","star","start","state","statement","station","status","stay","steak","steal","step","stick","still","stock","stomach","stop","storage","store","storm","story","strain","stranger","strategy","street","strength","stress","stretch","strike","string","strip","stroke","structure","struggle","student","studio","study","stuff","stupid","style","subject","substance","success","suck","sugar","suggestion","suit","summer","sun","supermarket","support","surgery","surprise","surround","survey","suspect","sweet","swim","swimming","swing","switch","sympathy","system", 152 | "table","tackle","tale","talk","tank","tap","target","task","taste","tax","tea","teach","teacher","teaching","team","tear","technology","telephone","television","tell","temperature","temporary","tennis","tension","term","test","text","thanks","theme","theory","thing","thought","throat","ticket","tie","till","time","tip","title","today","toe","tomorrow","tone","tongue","tonight","tool","tooth","top","topic","total","touch","tough","tour","tourist","towel","tower","town","track","trade","tradition","traffic","train","trainer","training","transition","transportation","trash","travel","treat","tree","trick","trip","trouble","truck","trust","truth","try","tune","turn","twist","two","type", 153 | "uncle","understanding","union","unique","unit","university","upper","upstairs","use","user","usual", 154 | "vacation","valuable","value","variation","variety","vast","vegetable","vehicle","version","video","view","village","virus","visit","visual","voice","volume", 155 | "wait","wake","walk","wall","war","warning","wash","watch","water","wave","way","weakness","wealth","wear","weather","web","wedding","week","weekend","weight","weird","welcome","west","western","wheel","whereas","while","white","whole","wife","will","win","wind","window","wine","wing","winner","winter","wish","witness","woman","wonder","wood","word","work","worker","working","world","worry","worth","wrap","writer","writing", 156 | "yard","year","yellow","yesterday","you","young","youth","zone" 157 | ] 158 | 159 | 160 | # Sort by length and cache list ranges 161 | ADJECTIVES.sort(key=lambda x: len(x)) 162 | NOUNS.sort(key=lambda x: len(x)) 163 | ADJECTIVES_LENGTHS = { l: sum(1 for a in ADJECTIVES if len(a) <= l) for l in (3, 4, 5, 6, 7, 8, 9) } 164 | NOUNS_LENGTHS = { l: sum(1 for a in NOUNS if len(a) <= l) for l in (3, 4, 5, 6, 7, 8, 9) } 165 | 166 | 167 | def codenamize_particles(obj = None, adjectives = 1, max_item_chars = 0, hash_algo = 'md5'): 168 | """ 169 | Returns an array a list of consistent codenames for the given object, by joining random 170 | adjectives and words together. 171 | 172 | Args: 173 | obj (int|string): The object to assign a codename. 174 | adjectives (int): Number of adjectives to use (default 1). 175 | max_item_chars (int): Max characters of each part of the codename (0 for no limit). 176 | 177 | Changing max_item_length will produce different results for the same objects, 178 | so existing mapped codenames will change substantially. 179 | 180 | Using None as object will make this function return the size of the 181 | codename space for the given options as an integer. 182 | """ 183 | 184 | # Minimum length of 3 is required 185 | if max_item_chars > 0 and max_item_chars < 3: 186 | max_item_chars = 3 187 | if max_item_chars > 9: 188 | max_item_chars = 0 189 | 190 | # Prepare codename word lists and calculate size of codename space 191 | particles = [ NOUNS ] + [ ADJECTIVES for _ in range(0, adjectives) ] 192 | if max_item_chars > 0: 193 | particles[0] = NOUNS[:NOUNS_LENGTHS[max_item_chars]] 194 | particles[1:] = [ ADJECTIVES[:ADJECTIVES_LENGTHS[max_item_chars]] for _ in range(0, adjectives) ] 195 | 196 | total_words = functools.reduce(lambda a, b: a * b, [len(p) for p in particles], 1) 197 | 198 | # Return size of codename space if no object is passed 199 | if obj is None: 200 | return total_words 201 | 202 | # Convert numbers to strings 203 | if isinstance(obj, six.integer_types): 204 | obj = str(obj) 205 | 206 | if isinstance(obj, six.text_type): 207 | obj = obj.encode('utf-8') 208 | 209 | hh = hashlib.new(hash_algo) 210 | hh.update(obj) 211 | obj_hash = int(hh.hexdigest(), 16) * 36413321723440003717 # TODO: With next breaking change, remove the prime factor (and test) 212 | 213 | # Calculate codename words 214 | index = obj_hash % total_words 215 | codename_particles = [] 216 | for p in particles: 217 | codename_particles.append(p[(index) % len(p)]) 218 | index = int(index / len(p)) 219 | 220 | codename_particles.reverse() 221 | 222 | return codename_particles 223 | 224 | 225 | def codenamize_space(adjectives, max_item_chars, hash_algo = 'md5'): 226 | """ 227 | Returns the size of the codename space for the given parameters. 228 | """ 229 | 230 | return codenamize_particles(None, adjectives, max_item_chars, hash_algo) 231 | 232 | 233 | def codenamize(obj, adjectives = 1, max_item_chars = 0, join = "-", capitalize = False, hash_algo = 'md5'): 234 | """ 235 | Returns a consistent codename for the given object, by joining random 236 | adjectives and words together. 237 | 238 | Args: 239 | obj (int|string): The object to assign a codename. 240 | adjectives (int): Number of adjectives to use (default 1). 241 | max_item_chars (int): Max characters of each part of the codename (0 for no limit). 242 | join: (string) Stromg used to join codename parts (default "-"). 243 | capitalize (boolean): Capitalize first letter of each word (default False). 244 | 245 | Changing max_item_length will produce different results for the same objects, 246 | so existing mapped codenames will change substantially. 247 | """ 248 | 249 | codename_particles = codenamize_particles(obj, adjectives, max_item_chars, hash_algo) 250 | 251 | if join is None: 252 | join = "" 253 | if capitalize: 254 | codename_particles = [ p[0].upper() + p[1:] for p in codename_particles] 255 | 256 | codename = join.join(codename_particles) 257 | 258 | return codename 259 | 260 | 261 | def print_test(): 262 | """ 263 | Test and example function for the "codenamize" module. 264 | """ 265 | print("OBJ ADJ0-MAX5 ADJ1-MAX5 ADJ2-MAX5 ADJ-0, ADJ-1, ADJ-2 (capitalized, empty join character)") 266 | for v in range(100001, 100010): 267 | print("%6s %11s %11s %17s %s, %s, %s" % (v, codenamize(v, 0, 5), codenamize(v, 1, 5), codenamize(v, 2, 5), 268 | codenamize(v, 0, 0, "", True), codenamize(v, 1, 0, "", True), codenamize(v, 2, 0, "", True))) 269 | 270 | print("codenamize SPACE SIZES") 271 | for a in range(0, 3): 272 | for m in (3, 4, 5, 6, 7, 0): 273 | print("%d adj (max %d chars) = %d combinations" % (a, m, codenamize_space(a, m))) 274 | 275 | print("TESTS") 276 | l1 = list(set( [ codenamize(a, 1, 3) for a in range(0, 2760 + 17) ] )) 277 | l2 = list(set( [ codenamize(a, 2, 3) for a in range(0, 66240 + 17) ] )) 278 | print(" (*, 1 adj, max 3) => %d distinct results (space size is %d)" % (len(l1), codenamize_space(1, 3))) 279 | print(" (*, 2 adj, max 3) => %d distinct results (space size is %d)" % (len(l2), codenamize_space(2, 3))) 280 | print(" (100001, 1 adj, max 5) => %s (must be 'funny-boat')" % (codenamize(100001, 1, 5))) 281 | print(" ('100001', 1 adj, max 5) => %s (must be 'funny-boat')" % (codenamize('100001', 1, 5))) 282 | print(" (u'100001', 1 adj, max 5) => %s (must be 'funny-boat')" % (codenamize(u'100001', 1, 5))) 283 | 284 | 285 | def main(): 286 | 287 | parser = argparse.ArgumentParser(description='Generate consistent easier-to-remember codenames from strings and numbers.') 288 | parser.add_argument('strings', nargs='*', help="One or more strings to codenamize.") 289 | parser.add_argument('-p', '--prefix', dest='prefix', action='store', type=int, default=1, help='number of prefixes to use') 290 | parser.add_argument('-m', '--maxchars', dest='maxchars', action='store', type=int, default=0, help='max word characters (0 for no limit)') 291 | parser.add_argument('-a', '--hash_algorithm', dest='hash_algo', action='store', type=str, default='md5', 292 | help='the algorithm to use to hash the input value (default: md5)') 293 | parser.add_argument('-j', '--join', dest='join', action='store', default="-", help='separator between words (default: -)') 294 | parser.add_argument('-c', '--capitalize', dest='capitalize', action='store_true', help='capitalize words') 295 | parser.add_argument('--space', dest='space', action='store_true', help='show codename space for the given arguments') 296 | parser.add_argument('--tests', dest='tests', action='store_true', help='show information and samples') 297 | parser.add_argument('--list_algorithms', dest='list_algorithms', action='store_true', 298 | help='List the hash algorithms available') 299 | parser.add_argument('--version', action='version', version='codenamize %s' % ("1.2.3")) 300 | 301 | args = parser.parse_args() 302 | 303 | if args.list_algorithms: 304 | for a in hashlib.algorithms_available: 305 | print(a) 306 | return 307 | 308 | if args.tests: 309 | print_test() 310 | return 311 | 312 | if args.space: 313 | print(codenamize_space(args.prefix, args.maxchars, args.hash_algo)) 314 | return 315 | 316 | if len(args.strings) == 0: 317 | parser.print_usage() 318 | return 319 | 320 | for o in args.strings: 321 | print(codenamize(o, args.prefix, args.maxchars, args.join, args.capitalize, args.hash_algo)) 322 | 323 | 324 | if __name__ == "__main__": 325 | main() 326 | 327 | --------------------------------------------------------------------------------