I'm getting started with Python and one of the beginner projects to learn the language was a password generator (one of the dozens already in CodeReview). I have a C# and JS background so I want to make sure I'm doing things the Python way.
Technically the include_punctuation
and include_digits
properties could be omitted and the exclusion list would be a custom concat of strings.digits+strings.punctuation
.
The reasoning behind the PasswordModel
is that any component that has an API of charset
and length
is a valid model. That would mean we could create a MemorablePasswordModel
for passwords such as "apple truck butterfly postcard" with a clean and separate model.
from random import choice
from string import digits, ascii_letters, punctuation
def filter_exclusions(items, exclusions):
result = []
for i in items:
if i not in exclusions:
result.append(i)
return result
class PasswordModel:
def __init__(self, length=8, include_symbols=True, include_digits=True, exclusion_list=""):
self.exclusion_list = list(exclusion_list)
self.length = length
self.include_symbols = include_symbols
self.include_digits = include_digits
def charset(self) -> str:
chars = [ascii_letters]
if self.include_symbols:
chars.append(punctuation)
if self.include_digits:
chars.append(digits)
return "".join(filter_exclusions("".join(chars), self.exclusion_list))
class PasswordGenerator:
def __init__(self, password_model=PasswordModel()):
self.model = password_model
def generate(self) -> str:
charset = self.model.charset()
return "".join(choice(charset) for _ in range(self.model.length))
# Test it out
model = PasswordModel(length=24, exclusion_list="\\/@%")
gen = PasswordGenerator()
print(gen.generate())
Questions
- Is there a cleaner way to "include" symbols and digits, I just appended them to a list.
- Is there anything built-in to exclude one list from another?