Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ pip install cs50

## Usage

import cs50
```
import cs50

...
...

c = cs50.get_char();
f = cs50.get_float();
i = cs50.get_int();
s = cs50.get_string();
f = cs50.get_float();
i = cs50.get_int();
s = cs50.get_string();
```
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
package_dir={"": "src"},
packages=["cs50"],
url="https://github.com/cs50/python-cs50",
version="3.2.0"
version="4.0.0"
)
87 changes: 17 additions & 70 deletions src/cs50/cs50.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
from __future__ import print_function

import inspect
import os
import re
import sys

from distutils.sysconfig import get_python_lib
from os.path import abspath, join
from termcolor import colored
from traceback import extract_tb, format_list, format_exception_only, format_exception
from traceback import format_exception


class flushfile():
class _flushfile():
"""
Disable buffering for standard output and standard error.

Expand All @@ -28,23 +29,11 @@ def write(self, x):
self.f.flush()


sys.stderr = flushfile(sys.stderr)
sys.stdout = flushfile(sys.stdout)
sys.stderr = _flushfile(sys.stderr)
sys.stdout = _flushfile(sys.stdout)


def eprint(*args, **kwargs):
"""
Print an error message to standard error, prefixing it with
file name and line number from which method was called.
"""
end = kwargs.get("end", "\n")
sep = kwargs.get("sep", " ")
(filename, lineno) = inspect.stack()[1][1:3]
print("{}:{}: ".format(filename, lineno), end="")
print(*args, end=end, file=sys.stderr, sep=sep)


def formatException(type, value, tb):
def _formatException(type, value, tb):
"""
Format traceback, darkening entries from global site-packages directories
and user-specific site-packages directory.
Expand All @@ -67,28 +56,18 @@ def formatException(type, value, tb):
return "".join(lines).rstrip()


sys.excepthook = lambda type, value, tb: print(formatException(type, value, tb), file=sys.stderr)
sys.excepthook = lambda type, value, tb: print(_formatException(type, value, tb), file=sys.stderr)


def get_char(prompt=None):
"""
Read a line of text from standard input and return the equivalent char;
if text is not a single char, user is prompted to retry. If line can't
be read, return None.
"""
while True:
s = get_string(prompt)
if s is None:
return None
if len(s) == 1:
return s[0]
def eprint(*args, **kwargs):
raise RuntimeError("The CS50 Library for Python no longer supports eprint, but you can use print instead!")

# Temporarily here for backwards compatibility
if prompt is None:
print("Retry: ", end="")

def get_char(prompt):
raise RuntimeError("The CS50 Library for Python no longer supports get_char, but you can use get_string instead!")

def get_float(prompt=None):

def get_float(prompt):
"""
Read a line of text from standard input and return the equivalent float
as precisely as possible; if text does not represent a double, user is
Expand All @@ -104,12 +83,8 @@ def get_float(prompt=None):
except ValueError:
pass

# Temporarily here for backwards compatibility
if prompt is None:
print("Retry: ", end="")


def get_int(prompt=None):
def get_int(prompt):
"""
Read a line of text from standard input and return the equivalent int;
if text does not represent an int, user is prompted to retry. If line
Expand All @@ -121,40 +96,12 @@ def get_int(prompt=None):
return None
if re.search(r"^[+-]?\d+$", s):
try:
i = int(s, 10)
if type(i) is int: # Could become long in Python 2
return i
return int(s, 10)
except ValueError:
pass

# Temporarily here for backwards compatibility
if prompt is None:
print("Retry: ", end="")


if sys.version_info.major != 3:
def get_long(prompt=None):
"""
Read a line of text from standard input and return the equivalent long;
if text does not represent a long, user is prompted to retry. If line
can't be read, return None.
"""
while True:
s = get_string(prompt)
if s is None:
return None
if re.search(r"^[+-]?\d+$", s):
try:
return long(s, 10)
except ValueError:
pass

# Temporarily here for backwards compatibility
if prompt is None:
print("Retry: ", end="")


def get_string(prompt=None):

def get_string(prompt):
"""
Read a line of text from standard input and return it as a string,
sans trailing line ending. Supports CR (\r), LF (\n), and CRLF (\r\n)
Expand Down
12 changes: 6 additions & 6 deletions src/cs50/flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from os import getenv
from pkg_resources import get_distribution

from .cs50 import formatException
from .cs50 import _formatException

# Try to monkey-patch Flask, if installed
try:
Expand All @@ -18,7 +18,7 @@
# https://docs.python.org/3/library/logging.html#logging.Formatter.formatException
try:
import flask.logging
flask.logging.default_handler.formatter.formatException = lambda exc_info: formatException(*exc_info)
flask.logging.default_handler.formatter.formatException = lambda exc_info: _formatException(*exc_info)
except Exception:
pass

Expand All @@ -42,16 +42,16 @@ def _after(*args, **kwargs):
logging.getLogger("cs50").disabled = disabled
SQL.execute = _after

# Add support for Cloud9 proxy so that flask.redirect doesn't redirect from HTTPS to HTTP
# http://stackoverflow.com/a/23504684/5156190
# When behind CS50 IDE's proxy, ensure that flask.redirect doesn't redirect from HTTPS to HTTP
# https://werkzeug.palletsprojects.com/en/0.15.x/middleware/proxy_fix/#module-werkzeug.middleware.proxy_fix
if getenv("C9_HOSTNAME") and not getenv("IDE_OFFLINE"):
try:
import flask
from werkzeug.contrib.fixers import ProxyFix
from werkzeug.middleware.proxy_fix import ProxyFix
_before = flask.Flask.__init__
def _after(*args, **kwargs):
_before(*args, **kwargs)
self.wsgi_app = ProxyFix(self.wsgi_app)
self.wsgi_app = ProxyFix(self.wsgi_app, x_proto=1)
flask.Flask.__init__ = _after
except:
pass
Expand Down