adds file handling and login generator
This commit is contained in:
parent
8dc74e59e8
commit
83e42b682c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,56 @@
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
def load_file(filename):
|
||||||
|
"""
|
||||||
|
We load a file and make a list out of it. Note that the same function is
|
||||||
|
used for both files (both adjectives and subjects). Functions should be
|
||||||
|
made as generic as possible.
|
||||||
|
|
||||||
|
There IS a problem you can fix, some logins will have spaces in them. Try
|
||||||
|
to remove them in this function!
|
||||||
|
"""
|
||||||
|
words = []
|
||||||
|
with open(filename, "r") as fp:
|
||||||
|
lines = fp.readlines()
|
||||||
|
for line in lines:
|
||||||
|
words.append(line.strip()) # what does strip() do, what does append() do? remember CTRL+Q!
|
||||||
|
return words
|
||||||
|
|
||||||
|
|
||||||
|
def generate_username():
|
||||||
|
"""
|
||||||
|
We'll generate a random pair of adjectives and subjects from two wordlists.
|
||||||
|
You NEED to have both files in you python project for this to work! Note
|
||||||
|
the capitalize method call to make it all prettier...
|
||||||
|
"""
|
||||||
|
adjectives = load_file("./adjectives.txt")
|
||||||
|
subjects = load_file("./subjects.txt")
|
||||||
|
adjective = random.choice(adjectives)
|
||||||
|
subject = random.choice(subjects)
|
||||||
|
username = adjective.capitalize() + subject.capitalize()
|
||||||
|
return username
|
||||||
|
|
||||||
|
|
||||||
|
def generate_password(length=10, complictated=True):
|
||||||
|
"""
|
||||||
|
We generate a password with default settings. You can overide these by
|
||||||
|
changing the arguments in the function call.
|
||||||
|
"""
|
||||||
|
password = ""
|
||||||
|
if complictated:
|
||||||
|
chars = string.ascii_letters + string.digits + string.punctuation
|
||||||
|
else:
|
||||||
|
chars = string.ascii_letters
|
||||||
|
for i in range(0, length):
|
||||||
|
password += random.choice(chars)
|
||||||
|
return password
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# let's do some testing!
|
||||||
|
username_test = generate_username()
|
||||||
|
print(username_test)
|
||||||
|
password_test = generate_password()
|
||||||
|
print(password_test)
|
|
@ -0,0 +1,61 @@
|
||||||
|
import login_generator
|
||||||
|
|
||||||
|
|
||||||
|
def prompt():
|
||||||
|
"""
|
||||||
|
We prompt but you KNOW how this works!
|
||||||
|
"""
|
||||||
|
response = ""
|
||||||
|
while not response.isdigit():
|
||||||
|
response = input("how many login pairs would you like to create?")
|
||||||
|
return int(response)
|
||||||
|
|
||||||
|
|
||||||
|
def how_long():
|
||||||
|
"""
|
||||||
|
And again... (we could combine both prompts, but how?)
|
||||||
|
"""
|
||||||
|
response = ""
|
||||||
|
while not response.isdigit():
|
||||||
|
response = input("how long should the password be?")
|
||||||
|
return int(response)
|
||||||
|
|
||||||
|
|
||||||
|
def complex_or_not():
|
||||||
|
response = ""
|
||||||
|
while response.lower() not in ["y", "n"]:
|
||||||
|
response = input("you want complex passwords? (y/n)")
|
||||||
|
if response.lower() == "y":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def create_login(length, complicated):
|
||||||
|
"""
|
||||||
|
We use our library to generate the username and password. The double return
|
||||||
|
might look confusing but just look at the for loop in the generate_logins
|
||||||
|
functions and you'll see how it unpacks...
|
||||||
|
"""
|
||||||
|
username = login_generator.generate_username()
|
||||||
|
password = login_generator.generate_password(length, complicated)
|
||||||
|
return username, password
|
||||||
|
|
||||||
|
|
||||||
|
def generate_logins(number, length, complicated):
|
||||||
|
"""
|
||||||
|
Easy no? But what does the i do? Do we really need it's value?
|
||||||
|
"""
|
||||||
|
for i in range(0, number):
|
||||||
|
username, password = create_login(length, complicated)
|
||||||
|
print("username {}: {}".format(i, username))
|
||||||
|
print("password {}: {}".format(i, password))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Here we go!
|
||||||
|
number_of_logins = prompt()
|
||||||
|
complicted = complex_or_not()
|
||||||
|
length = how_long()
|
||||||
|
generate_logins(number_of_logins, length, complicted)
|
||||||
|
|
|
@ -0,0 +1,239 @@
|
||||||
|
Aardvark
|
||||||
|
African elephant
|
||||||
|
Albatross
|
||||||
|
Alley cat
|
||||||
|
Alligator
|
||||||
|
Amphibian
|
||||||
|
Ant
|
||||||
|
Anteater
|
||||||
|
Antelope
|
||||||
|
Ape
|
||||||
|
Armadillo
|
||||||
|
Asian elephant
|
||||||
|
Baboon
|
||||||
|
Badger
|
||||||
|
Bat
|
||||||
|
Bear
|
||||||
|
Beaver
|
||||||
|
Beetle
|
||||||
|
Billy goat
|
||||||
|
Bison
|
||||||
|
Boar
|
||||||
|
Bobcat
|
||||||
|
Bovine
|
||||||
|
Bronco
|
||||||
|
Buck
|
||||||
|
Buffalo
|
||||||
|
Bug
|
||||||
|
Bull
|
||||||
|
Bunny
|
||||||
|
BunnyCalf
|
||||||
|
Camel
|
||||||
|
Canary
|
||||||
|
Canine
|
||||||
|
Caribou
|
||||||
|
Cat
|
||||||
|
Caterpillar
|
||||||
|
Centipede
|
||||||
|
Chanticleer
|
||||||
|
Cheetah
|
||||||
|
Chick
|
||||||
|
Chimpanzee
|
||||||
|
Chinchilla
|
||||||
|
Chipmunk
|
||||||
|
Clam
|
||||||
|
Cockatiel
|
||||||
|
Colt
|
||||||
|
Condor
|
||||||
|
Cougar
|
||||||
|
Cow
|
||||||
|
Coyote
|
||||||
|
Crab
|
||||||
|
Crane
|
||||||
|
Creature
|
||||||
|
Crocodile
|
||||||
|
Crow
|
||||||
|
Cub
|
||||||
|
Cur
|
||||||
|
Cygnet
|
||||||
|
Deer
|
||||||
|
Dingo
|
||||||
|
Dodo
|
||||||
|
Doe
|
||||||
|
Dog
|
||||||
|
Dolphin
|
||||||
|
Donkey
|
||||||
|
Dove
|
||||||
|
Drake
|
||||||
|
Duck
|
||||||
|
Eagle
|
||||||
|
Egret
|
||||||
|
Elephant
|
||||||
|
Elk
|
||||||
|
Emu
|
||||||
|
Ewe
|
||||||
|
Falcon
|
||||||
|
Fawn
|
||||||
|
Feline
|
||||||
|
Ferret
|
||||||
|
Flamingo
|
||||||
|
Flee
|
||||||
|
Flies
|
||||||
|
Foal
|
||||||
|
Fowl
|
||||||
|
Fox
|
||||||
|
Frog
|
||||||
|
Gander
|
||||||
|
Gazelle
|
||||||
|
Gelding
|
||||||
|
Gerbil
|
||||||
|
Gibbon
|
||||||
|
Giraffe
|
||||||
|
Goat
|
||||||
|
Goose
|
||||||
|
Gopher
|
||||||
|
Gorilla
|
||||||
|
Grizzly bear
|
||||||
|
Guinea pig
|
||||||
|
Hamster
|
||||||
|
Hare
|
||||||
|
Hawk
|
||||||
|
Hedgehog
|
||||||
|
Heifer
|
||||||
|
Hippopotamus
|
||||||
|
Horse
|
||||||
|
Hound
|
||||||
|
Hummingbird
|
||||||
|
Hyena
|
||||||
|
Ibis
|
||||||
|
Iguana
|
||||||
|
Jackal
|
||||||
|
Jackrabbit
|
||||||
|
Jaguar
|
||||||
|
Javalina
|
||||||
|
Jellyfish
|
||||||
|
Jenny
|
||||||
|
Joey
|
||||||
|
Kangaroo
|
||||||
|
Kid
|
||||||
|
Kitten
|
||||||
|
Kiwi
|
||||||
|
Koala
|
||||||
|
Komodo dragon
|
||||||
|
Krill
|
||||||
|
Lamb
|
||||||
|
Lemming
|
||||||
|
Lemur
|
||||||
|
Leopard
|
||||||
|
Lion
|
||||||
|
Lioness
|
||||||
|
Llama
|
||||||
|
Lobster
|
||||||
|
Lynx
|
||||||
|
Macaw
|
||||||
|
Manatee
|
||||||
|
Marmoset
|
||||||
|
Marmot
|
||||||
|
Mink
|
||||||
|
Minnow
|
||||||
|
Mite
|
||||||
|
Mockingbird
|
||||||
|
Mole
|
||||||
|
Mongoose
|
||||||
|
Mongrel
|
||||||
|
Monkey
|
||||||
|
Moose
|
||||||
|
Mouse
|
||||||
|
Mule
|
||||||
|
Mustang
|
||||||
|
Mutt
|
||||||
|
Nag
|
||||||
|
Narwhale
|
||||||
|
Newt
|
||||||
|
Ocelot
|
||||||
|
Octopus
|
||||||
|
Opossum
|
||||||
|
Orangutan
|
||||||
|
Orca
|
||||||
|
Osprey
|
||||||
|
Ostrich
|
||||||
|
Otter
|
||||||
|
Owl
|
||||||
|
Ox
|
||||||
|
Pachyderm
|
||||||
|
Panda
|
||||||
|
Panther
|
||||||
|
Parakeet
|
||||||
|
Parrot
|
||||||
|
Peacock
|
||||||
|
Pelican
|
||||||
|
Penguin
|
||||||
|
Pheasant
|
||||||
|
Pig
|
||||||
|
Pigeon
|
||||||
|
Piglet
|
||||||
|
Platypus
|
||||||
|
Pony
|
||||||
|
Pooch
|
||||||
|
Porcupine
|
||||||
|
Porpoise
|
||||||
|
Primate
|
||||||
|
Puppy
|
||||||
|
Pussycat
|
||||||
|
Rabbit
|
||||||
|
Raccoon
|
||||||
|
Ram
|
||||||
|
Rat
|
||||||
|
Reptiles
|
||||||
|
Rhinoceros
|
||||||
|
Robin
|
||||||
|
Rooster
|
||||||
|
Salamander
|
||||||
|
Sea lion
|
||||||
|
Seagull
|
||||||
|
Seal
|
||||||
|
Sheep
|
||||||
|
Sidewinder
|
||||||
|
Skunk
|
||||||
|
Sloth
|
||||||
|
Snail
|
||||||
|
Snake
|
||||||
|
Songbird
|
||||||
|
Sow
|
||||||
|
Spider
|
||||||
|
Squid
|
||||||
|
Squirrel
|
||||||
|
Stallion
|
||||||
|
Steer
|
||||||
|
Stork
|
||||||
|
Stork
|
||||||
|
Swan
|
||||||
|
Tadpole
|
||||||
|
Tapir
|
||||||
|
Terrapin
|
||||||
|
Thoroughbred
|
||||||
|
Tiger
|
||||||
|
Toad
|
||||||
|
Tortoise
|
||||||
|
Toucan
|
||||||
|
Turkey
|
||||||
|
Uakari
|
||||||
|
Unicorn
|
||||||
|
Vixen
|
||||||
|
Vole
|
||||||
|
Vulture
|
||||||
|
Wallaby
|
||||||
|
Walrus
|
||||||
|
Warthog
|
||||||
|
Wasp
|
||||||
|
Weasel
|
||||||
|
Whale
|
||||||
|
Wildebeast
|
||||||
|
Wolf
|
||||||
|
Wombat
|
||||||
|
Woodpecker
|
||||||
|
Worm
|
||||||
|
X-ray fish
|
||||||
|
Yak
|
||||||
|
Zebra
|
||||||
|
|
|
@ -1509,23 +1509,129 @@ print(digits)
|
||||||
|
|
||||||
# Handling files
|
# Handling files
|
||||||
|
|
||||||
|
When we `import` a library python will read and execute the file in question.
|
||||||
|
We can also just *read* a simple text file and *use* the data that's in the file.
|
||||||
|
There are two ways of reading a file, one more *pythonic* and one more linear.
|
||||||
|
I'll outline both and you can use whichever seems more logical to you.
|
||||||
|
|
||||||
## Reading from a file
|
## Reading from a file
|
||||||
|
|
||||||
|
### In-line way
|
||||||
|
|
||||||
|
The builtin function `open` is what's new here.
|
||||||
|
It takes two arguments, one is the [path](https://en.wikipedia.org/wiki/Path_(computing)) and the other is a *mode*.
|
||||||
|
The most used modes are **read** or **write**, and this as either **text** or **binary**.
|
||||||
|
Have a look at the documentation to discover more modes.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
fp = open("./examples/data.txt", "r")
|
||||||
|
data = fp.readlines()
|
||||||
|
print("file contains: {}".format(data))
|
||||||
|
fp.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pythonic way
|
||||||
|
|
||||||
|
The *exact* same thing can be done in a more pythonic way as follows.
|
||||||
|
The beauty of the `with` syntax is that the `close` function call is implied by the indentation.
|
||||||
|
I personally prefer this way of reading and writing files but you do you!
|
||||||
|
|
||||||
|
```python3
|
||||||
|
file_to_open = "./examples/data.txt"
|
||||||
|
|
||||||
|
with open(file_to_open, "r") as fp:
|
||||||
|
data = fp.readlines()
|
||||||
|
print("file contains: {}".format(data))
|
||||||
|
|
||||||
|
print("{} has {} lines".format(file_to_open, len(data)))
|
||||||
|
```
|
||||||
|
|
||||||
## Writing to a file
|
## Writing to a file
|
||||||
|
|
||||||
## csv, JSON and yaml
|
Writing to a file can also be done in two ways, a pythonic and *less* pythonic way.
|
||||||
|
As I prefer the pythonic way I'll only showcase that one but you'll be able to easily adapt the code yourself.
|
||||||
|
The only difference is the **mode** we use to `open` the file.
|
||||||
|
|
||||||
## pickle
|
```python3
|
||||||
|
first_name = input("what's your first name? ")
|
||||||
|
last_name = input("what's your last name? ")
|
||||||
|
birthday = input("what's your date of birth? ")
|
||||||
|
|
||||||
|
data = [first_name, last_name, birthday]
|
||||||
|
|
||||||
|
file_to_open = "./examples/test.tmp"
|
||||||
|
|
||||||
|
with open(file_to_open, "w") as fp:
|
||||||
|
for element in data:
|
||||||
|
fp.write("{}\n".format(element))
|
||||||
|
print("done!")
|
||||||
|
```
|
||||||
|
|
||||||
|
There is also a way to write a batch of lines to a file in one go.
|
||||||
|
This is done as follows.
|
||||||
|
But, you'll notice there is no **newline** added after each element.
|
||||||
|
|
||||||
|
```python3
|
||||||
|
data = ["wouter", "gordts", "1986"]
|
||||||
|
|
||||||
|
file_to_open = "./examples/test.tmp"
|
||||||
|
|
||||||
|
with open(file_to_open, "w") as fp:
|
||||||
|
fp.writelines(data)
|
||||||
|
```
|
||||||
|
|
||||||
# Coding challenge - Login generator
|
# Coding challenge - Login generator
|
||||||
|
|
||||||
TODO write a login generator as a library with a cli as program
|
Can you write me a program that creates random, but easy to remember, usernames?
|
||||||
BONUS argparse, save to file, read from file
|
Plus, for each username also a *not-so-easy-to-remember* password?
|
||||||
|
Maybe with a bit of flexibility?
|
||||||
|
For example variable password length?
|
||||||
|
|
||||||
|
This is an exercise you can take pretty far if you plan it out properly.
|
||||||
|
I would advise you to write the **generator** functions as a library.
|
||||||
|
Then import those functions into the program where you implement the user facing logic.
|
||||||
|
By doing so you can reuse your code for multiple interfaces (CLI, TUI, [argparse](https://docs.python.org/3/howto/argparse.html)).
|
||||||
|
If you want to you can also **save** your logins to a file!
|
||||||
|
|
||||||
|
An example of the output I expect:
|
||||||
|
|
||||||
|
```
|
||||||
|
how many login pairs would you like to create?3
|
||||||
|
you want complex passwords? (y/n)y
|
||||||
|
how long should the password be?32
|
||||||
|
username 0: EarnestCrocodile
|
||||||
|
password 0: :sdGV&[FDYZZ|RXUpZeo`J&t@*Z>^fEW
|
||||||
|
username 1: AbstractedDragon
|
||||||
|
password 1: 32hz5&C@<o\OMa9tnET(lk(3wF%d?$Dy
|
||||||
|
username 2: MeekStallion
|
||||||
|
password 2: +;^di8a":AD;_b4^w$Fj'RVkI`CoG,LX
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning</summary>
|
||||||
|
|
||||||
|
This spoiler warning is in multiple steps.
|
||||||
|
If you're unsure how to generate the *random-yet-easy-to-remember* have a look at [this file](./assets/subjects.txt) and [this file](./assets/adjectives.txt).
|
||||||
|
|
||||||
|
**Stop here and try it out!**
|
||||||
|
|
||||||
|
If you're unsure how to tackle the *library part* of this exercise, have a look at [this file](./assets/login_generator.py).
|
||||||
|
Don't just copy this code, read it and recreate it yourself!
|
||||||
|
|
||||||
|
**Stop here and try it out!**
|
||||||
|
|
||||||
|
Once the library is done you can code the *interface*.
|
||||||
|
For some inspiration for a simple question/response system you can have a look [here](./assets/pwd_cli.py).
|
||||||
|
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
# Dictionaries as data containers
|
# Dictionaries as data containers
|
||||||
|
|
||||||
TODO adapt the login generator to output a dict
|
TODO adapt the login generator to output a dict
|
||||||
|
|
||||||
|
## csv, JSON and yaml
|
||||||
|
|
||||||
# Creating our own classes
|
# Creating our own classes
|
||||||
|
|
||||||
## Class examples
|
## Class examples
|
||||||
|
|
Loading…
Reference in New Issue