-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
270 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: Python Password Generator | ||
|
||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
branches: [ main ] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Set up Python 3.10 | ||
uses: actions/setup-python@v1 | ||
with: | ||
python-version: '3.10' | ||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install setuptools wheel twine | ||
- name: Test with unittest | ||
run: | | ||
python3 -m unittest discover . | ||
- name: Creating package | ||
run: | | ||
python3 setup.py bdist_wheel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import string | ||
import random | ||
from functools import reduce | ||
|
||
|
||
class Pwd: | ||
LOWER_CASES = string.ascii_lowercase | ||
UPPER_CASES = string.ascii_uppercase | ||
LETTERS = string.ascii_letters | ||
DIGITS = string.digits | ||
SPECIALS = string.punctuation | ||
|
||
def __init__(self): | ||
self.value = None | ||
self.choices = [] | ||
|
||
def _set(self, length=None): | ||
if length is not None and length <= 0: | ||
raise ValueError('Password length cannot be less than or equal to 0') | ||
if len(self.choices) == 0: | ||
raise ValueError('You must select at least one parameter if you wish to generate a password') | ||
|
||
self.value = ''.join( | ||
random.choices( | ||
reduce(lambda x, y: x + y, self.choices), | ||
k=length or 10 | ||
) | ||
) | ||
return self | ||
|
||
|
||
class LowerCasesPassword(Pwd): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
def generate(self, length=None): | ||
""" | ||
Generate a password containing only lower-case letters | ||
:param int length: optional parameter (10 by default) | ||
""" | ||
|
||
self.choices = [self.LOWER_CASES] | ||
return self._set(length=length) | ||
|
||
|
||
class UpperCasesPassword(Pwd): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
def generate(self, length=None): | ||
""" | ||
Generate a password containing only upper-case letters | ||
:param int length: optional parameter (10 by default) | ||
""" | ||
|
||
self.choices = [self.UPPER_CASES] | ||
return self._set(length=length) | ||
|
||
|
||
class LettersPassword(Pwd): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
def generate(self, length=None): | ||
""" | ||
Generate a letter-only password | ||
:param int length: optional parameter (10 by default) | ||
""" | ||
|
||
self.choices = [self.LETTERS] | ||
return self._set(length=length) | ||
|
||
|
||
class DigitsPassword(Pwd): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
def generate(self, length=None): | ||
""" | ||
Generate a number-only password | ||
:param int length: optional parameter (10 by default) | ||
""" | ||
|
||
self.choices = [self.DIGITS] | ||
return self._set(length=length) | ||
|
||
|
||
class SpecialsPassword(Pwd): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
def generate(self, length=None): | ||
""" | ||
Generate a password containing only special characters | ||
:param int length: optional parameter (10 by default) | ||
""" | ||
|
||
self.choices = [self.SPECIALS] | ||
return self._set(length=length) | ||
|
||
|
||
class Password(Pwd): | ||
def __init__(self): | ||
super().__init__() | ||
|
||
def generate( | ||
self, | ||
length=None, | ||
lower_cases=True, | ||
upper_cases=True, | ||
digits=True, | ||
specials=True | ||
): | ||
""" | ||
Generate a password containing only special characters | ||
:param int length: optional parameter (10 by default) | ||
:param bool lower_cases: optional parameter (True by default) | ||
:param bool upper_cases: optional parameter (True by default) | ||
:param bool digits: optional parameter (True by default) | ||
:param bool specials: optional parameter (True by default) | ||
""" | ||
|
||
choices = [ | ||
self.LOWER_CASES, | ||
self.UPPER_CASES, | ||
self.DIGITS, | ||
self.SPECIALS | ||
] | ||
|
||
if not lower_cases: | ||
choices.remove(self.LOWER_CASES) | ||
if not upper_cases: | ||
choices.remove(self.UPPER_CASES) | ||
if not digits: | ||
choices.remove(self.DIGITS) | ||
if not specials: | ||
choices.remove(self.SPECIALS) | ||
|
||
self.choices = choices | ||
return self._set(length=length) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import unittest | ||
|
||
from pwd_generator import ( | ||
LowerCasesPassword, | ||
UpperCasesPassword, | ||
LettersPassword, | ||
DigitsPassword, | ||
SpecialsPassword, | ||
Password | ||
) | ||
|
||
|
||
class GeneratePasswordTestCase(unittest.TestCase): | ||
def test_generate_lower_cases_password(self): | ||
password = LowerCasesPassword() | ||
|
||
password.generate() | ||
self.assertEqual(len(password.value), 10) | ||
|
||
password.generate(length=20) | ||
self.assertEqual(len(password.value), 20) | ||
self.assertEqual(password.value.islower(), True) | ||
|
||
def test_generate_upper_cases_password(self): | ||
password = UpperCasesPassword() | ||
|
||
password.generate() | ||
self.assertEqual(len(password.value), 10) | ||
|
||
password.generate(length=12) | ||
self.assertEqual(len(password.value), 12) | ||
self.assertEqual(password.value.isupper(), True) | ||
|
||
def test_generate_letters_password(self): | ||
password = LettersPassword() | ||
|
||
password.generate() | ||
self.assertEqual(len(password.value), 10) | ||
|
||
password.generate(length=15) | ||
self.assertEqual(len(password.value), 15) | ||
|
||
def test_generate_digits_password(self): | ||
password = DigitsPassword() | ||
|
||
password.generate() | ||
self.assertEqual(len(password.value), 10) | ||
|
||
password.generate(length=17) | ||
self.assertEqual(len(password.value), 17) | ||
self.assertEqual(password.value.isnumeric(), True) | ||
|
||
def test_generate_specials_password(self): | ||
password = SpecialsPassword() | ||
|
||
password.generate() | ||
self.assertEqual(len(password.value), 10) | ||
|
||
password.generate(length=19) | ||
self.assertEqual(len(password.value), 19) | ||
|
||
def test_generate_custom_password(self): | ||
password = Password() | ||
|
||
password.generate() | ||
self.assertEqual(len(password.value), 10) | ||
|
||
password.generate( | ||
length=20, | ||
specials=False, | ||
digits=True, | ||
lower_cases=False | ||
) | ||
self.assertEqual(len(password.value), 20) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from pathlib import Path | ||
|
||
import setuptools | ||
from pkg_resources import parse_requirements | ||
|
||
with open("README.md", "r") as fh: | ||
long_description = fh.read() | ||
|
||
setuptools.setup( | ||
name="pwd_generator", | ||
version='0.0.1', | ||
author="Rémi Lopez", | ||
author_email="contact.remilopez@gmail.com", | ||
description="An open-source password generator", | ||
long_description=long_description, | ||
long_description_content_type="text/markdown", | ||
url="https://github.com/pwd-generator", | ||
packages=setuptools.find_packages(), | ||
classifiers=[ | ||
"Programming Language :: Python :: 3", | ||
"License :: OSI Approved :: MIT License", | ||
"Operating System :: OS Independent", | ||
], | ||
python_requires='>=3.8', | ||
include_package_data=True, | ||
) |