Skip to content

Commit d86f6d1

Browse files
authored
Merge pull request #266 from cs50/passphrase
support for lib50>3 and ssh passphrases
2 parents 818c546 + 3c1987b commit d86f6d1

File tree

2 files changed

+92
-19
lines changed

2 files changed

+92
-19
lines changed

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
'submit50': [('**.py', 'python', None),],
1616
},
1717
description="This is submit50, with which you can submit solutions to problems for CS50.",
18-
install_requires=["lib50>=2,<3", "requests>=2.19", "termcolor>=1.1"],
18+
install_requires=["lib50>=3,<4", "requests>=2.19", "termcolor>=1.1"],
1919
keywords=["submit", "submit50"],
2020
name="submit50",
2121
python_requires=">=3.6",
@@ -25,6 +25,6 @@
2525
entry_points={
2626
"console_scripts": ["submit50=submit50.__main__:main"]
2727
},
28-
version="3.0.4",
28+
version="3.1.0",
2929
include_package_data=True
3030
)

submit50/__main__.py

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
2-
import os
32
import argparse
3+
import enum
44
import gettext
55
import logging
66
import pkg_resources
@@ -21,6 +21,29 @@
2121

2222
SUBMIT_URL = "https://submit.cs50.io"
2323

24+
class LogLevel(enum.IntEnum):
25+
DEBUG = logging.DEBUG
26+
INFO = logging.INFO
27+
WARNING = logging.WARNING
28+
ERROR = logging.ERROR
29+
30+
31+
class ColoredFormatter(logging.Formatter):
32+
COLORS = {
33+
"ERROR": "red",
34+
"WARNING": "yellow",
35+
"DEBUG": "cyan",
36+
"INFO": "magenta",
37+
}
38+
39+
def __init__(self, fmt, use_color=True):
40+
super().__init__(fmt=fmt)
41+
self.use_color = use_color
42+
43+
def format(self, record):
44+
msg = super().format(record)
45+
return msg if not self.use_color else termcolor.colored(msg, getattr(record, "color", self.COLORS.get(record.levelname)))
46+
2447

2548
class Error(Exception):
2649
pass
@@ -50,6 +73,30 @@ def check_version():
5073
"Please upgrade."))
5174

5275

76+
def setup_logging(level):
77+
"""
78+
Sets up logging for lib50.
79+
level 'info' logs all git commands run to stderr
80+
level 'debug' logs all git commands and their output to stderr
81+
"""
82+
logger = logging.getLogger("lib50")
83+
84+
# Set verbosity level on the lib50 logger
85+
logger.setLevel(level.upper())
86+
87+
handler = logging.StreamHandler(sys.stderr)
88+
handler.setFormatter(ColoredFormatter("(%(levelname)s) %(message)s", use_color=sys.stderr.isatty()))
89+
90+
# Direct all logs to sys.stderr
91+
logger.addHandler(handler)
92+
93+
# Don't animate the progressbar if LogLevel is either info or debug
94+
lib50.ProgressBar.DISABLED = logger.level < LogLevel.WARNING
95+
96+
# Show exceptions when debugging
97+
excepthook.verbose = logger.level == LogLevel.DEBUG
98+
99+
53100
def cprint(text="", color=None, on_color=None, attrs=None, **kwargs):
54101
"""Colorizes text (and wraps to terminal's width)."""
55102
# Assume 80 in case not running in a terminal
@@ -62,7 +109,7 @@ def cprint(text="", color=None, on_color=None, attrs=None, **kwargs):
62109
color=color, on_color=on_color, attrs=attrs, **kwargs)
63110

64111

65-
def prompt(included, excluded):
112+
def prompt(honesty, included, excluded):
66113
if included:
67114
cprint(_("Files that will be submitted:"), "green")
68115
for file in included:
@@ -76,16 +123,33 @@ def prompt(included, excluded):
76123
for other in excluded:
77124
cprint("./{}".format(other), "yellow")
78125

126+
# If there's no honesty question, continue.
127+
if not honesty:
128+
return True
129+
79130
# Prompt for honesty
80131
try:
81-
answer = input(_("Keeping in mind the course's policy on academic honesty, "
82-
"are you sure you want to submit these files (yes/no)? "))
132+
# Show default message
133+
if honesty == True:
134+
honesty_question = _(
135+
"Keeping in mind the course's policy on academic honesty, "
136+
"are you sure you want to submit these files (yes/no)? "
137+
)
138+
# If a custom message is configured, show that instead
139+
else:
140+
honesty_question = str(honesty)
141+
142+
# Get the user's answer
143+
answer = input(honesty_question)
83144
except EOFError:
84145
answer = None
85146
print()
147+
148+
# If no answer given, or yes is not given, don't continue
86149
if not answer or not re.match(f"^\s*(?:{_('y|yes')})\s*$", answer, re.I):
87150
return False
88-
151+
152+
# Otherwise, do continue
89153
return True
90154

91155

@@ -102,9 +166,9 @@ def excepthook(type, value, tb):
102166

103167
cprint(_("Submission cancelled."), "red")
104168

105-
106169
excepthook.verbose = True
107170

171+
108172
class LogoutAction(argparse.Action):
109173
def __init__(self, option_strings, dest=argparse.SUPPRESS, default=argparse.SUPPRESS, help=_("logout of submit50")):
110174
super().__init__(option_strings, dest=dest, nargs=0, default=default, help=help)
@@ -124,20 +188,29 @@ def main():
124188

125189
parser = argparse.ArgumentParser(prog="submit50")
126190
parser.add_argument("--logout", action=LogoutAction)
127-
parser.add_argument("-v", "--verbose",
128-
action="store_true",
129-
help=_("show commands being executed"))
130-
parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {__version__}")
131-
parser.add_argument("slug", help=_(
132-
"prescribed identifier of work to submit"))
191+
parser.add_argument(
192+
"--log-level",
193+
action="store",
194+
default="warning",
195+
choices=[level.name.lower() for level in LogLevel],
196+
type=str.lower,
197+
help=_('warning: displays usage warnings.'
198+
'\ninfo: adds all commands run.'
199+
'\ndebug: adds the output of all commands run.')
200+
)
201+
parser.add_argument(
202+
"-V", "--version",
203+
action="version",
204+
version=f"%(prog)s {__version__}"
205+
)
206+
parser.add_argument(
207+
"slug",
208+
help=_("prescribed identifier of work to submit")
209+
)
133210

134211
args = parser.parse_args()
135212

136-
excepthook.verbose = args.verbose
137-
if args.verbose:
138-
logging.basicConfig(level=os.environ.get("SUBMIT50_LOGLEVEL", "INFO"))
139-
# Disable progress bar so it doesn't interfere with log
140-
lib50.ProgressBar.DISABLED = True
213+
setup_logging(args.log_level)
141214

142215
check_announcements()
143216
check_version()

0 commit comments

Comments
 (0)