-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeckutils.py
165 lines (121 loc) · 4.69 KB
/
deckutils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""This file contains functions for working with flashcard decks and flashcard files"""
from deck import Deck
import exceptions
from pathlib import Path
import os
from typing import Literal, Union
def deck_from_file(path: Path) -> Deck:
"""This fuction makes a deck from data in file at path"""
with path.open('r', encoding="utf-8") as file:
return Deck(file.read())
def get_deck_files(deck_dir: Path) -> list[Path]:
"""Returns a list with paths to all .deck files in a dir"""
decks: list[Path] = [] # Contains paths of decks
for file in deck_dir.iterdir():
if file.name.endswith("deck"):
decks.append(file)
return decks
def select_deck(deck_dir: Path) -> Deck:
"""Prompts the user to select a deck from the deck dir
Returns the deck the user selected."""
decks: list[Path] # Contains paths of decks
# Make sure path is actully a dir
if deck_dir.is_file():
raise ValueError(deck_dir)
# Get .deck files from deck_dir and add them to decks
decks = get_deck_files(deck_dir)
# Print before listing options
print("Please select a deck: \n")
# Now print out all of the decks and a coraponding number
deck: Path
for deck_index in range(len(decks)):
deck = decks[deck_index]
print(f"{deck_index + 1}. {deck.stem}")
# Contains index of choice, -1 is no choice made yet
choice: int = -1
# Uncheck choice, not checked
pchoice: int
schoice: str
# Loop until valid choice is made
while choice == -1:
schoice = input("Select a deck: ")
# Convert to int
try:
pchoice = int(schoice)
except ValueError:
print("Must type number. Try again")
continue
# Make sure not out of range
if not 1 < pchoice < len(decks):
print("Out of range. Try again")
continue
# Exit loop by setting choice
choice = pchoice
# Decks is just a list of paths of decks
# Choice is the index of the chosen deck + 1
return deck_from_file(decks[choice - 1])
def find_dropbox() -> Union[Path, Literal[False]]:
"""Try to find dropbox.
If it exists: return the Path for it
If it does not exist: return None"""
try: # Check for dropbox env var
return Path(os.environ["DROPBOX"])
except KeyError:
pass # If DROPBOX not set
# Look in defualt Dropbox location
if (Path.home() / "Dropbox").exists():
return Path.home() / "Dropbox"
return False
def get_decks_location(force_prompt: bool = False,
check_path: bool = True) -> Path:
"""Returns the dir that the decks are in
force_prompt: Do not check, just ask user to type path
check_path: Make sure path exists and is folder
Note: path is automaticlly check if dir is found automaticlly"""
# Just ask if force prompt
if force_prompt:
return ask_for_decks_location(to_check_path=check_path)
# Look for dropbox
dropbox: Union[Path, Literal[False]] = find_dropbox()
# If no dropbox, give up. dropbox being False breaks below code
if not dropbox: return ask_for_decks_location(to_check_path=check_path)
# Look for names of deck folders
item: Path
for item in dropbox.iterdir():
if item.stem.lower() == "decks":
# Make sure it is acually a folder first
if item.is_dir(): return item
if item.stem.lower() == "flashcards":
# Make sure it is acually a folder first
if item.is_dir(): return item
# If this runs, we could not find it in dropbox:
return ask_for_decks_location(to_check_path=check_path)
def ask_for_decks_location(to_check_path: bool = True) -> Path:
"""Just ask user for decks location"""
while True:
path = Path(input("Enter path to folder with deck files: ").rstrip())
if to_check_path:
if check_path(path): return path
continue
return path
def check_path(path: Path) -> bool:
"""Makes sure that the given path points is a folder that exists.
if passes tests: return True
if not passes tests: return False"""
# Make sure it is a valid path
try:
if not path.exists(): return False
except OSError:
# This means that an invalid path was passed
return False
# Make sure it is a folder
if not path.is_dir: return False
# Passed all tests
return True
def extract_answers(string: str) -> list[str]:
""""Takes a string and parses it to find all answers using deck syntax
This function currently only implements / operator"""
answers: list[str]
# Split over / operator
answers = string.split("/")
return answers