Skip to content

fixed style, naming of cs50.sql #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Nov 1, 2017
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
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
"Topic :: Software Development :: Libraries :: Python Modules"
],
description="CS50 library for Python",
install_requires=["SQLAlchemy", "sqlparse"],
install_requires=["SQLAlchemy", "sqlparse", "termcolor"],
keywords="cs50",
name="cs50",
package_dir={"": "src"},
packages=["cs50"],
url="https://github.com/cs50/python-cs50",
version="2.2.0"
version="2.3.0"
)
6 changes: 5 additions & 1 deletion src/cs50/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import imp
import sys

from .cs50 import *


class CustomImporter(object):
"""
Import cs50.SQL lazily so that rest of library can be used without SQLAlchemy installed.
Expand All @@ -11,14 +11,18 @@ class CustomImporter(object):
http://xion.org.pl/2012/05/06/hacking-python-imports/
http://dangerontheranger.blogspot.com/2012/07/how-to-use-sysmetapath-with-python.html
"""

def find_module(self, fullname, path=None):
if fullname == "cs50.SQL":
return self
return None

def load_module(self, name):
if name in sys.modules:
return sys.modules[name]
from .sql import SQL
sys.modules[name] = SQL
return SQL


sys.meta_path.append(CustomImporter())
40 changes: 38 additions & 2 deletions src/cs50/cs50.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
from __future__ import print_function

import inspect
import re
import sys

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


def excepthook(type, value, tb):
"""
Format traceback, darkening entries from global site-packages directories
and user-specific site-packages directory.

https://stackoverflow.com/a/46071447/5156190
"""
packages = tuple(join(abspath(p), "") for p in sys.path[1:])
for entry in extract_tb(tb):
fmt = format_list((entry,))
if (entry[0].startswith(packages)):
cprint("".join(fmt), attrs=["dark"], end="", file=sys.stderr)
else:
cprint("".join(fmt), end="", file=sys.stderr)
cprint("".join(format_exception_only(type, value)), end="")


sys.excepthook = excepthook


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

http://stackoverflow.com/a/231216
"""

def __init__(self, f):
self.f = f

Expand All @@ -18,9 +46,12 @@ def __getattr__(self, name):
def write(self, x):
self.f.write(x)
self.f.flush()


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


def eprint(*args, **kwargs):
"""
Print an error message to standard error, prefixing it with
Expand All @@ -32,6 +63,7 @@ def eprint(*args, **kwargs):
print("{}:{}: ".format(filename, lineno), end="")
print(*args, end=end, file=sys.stderr, sep=sep)


def get_char(prompt=None):
"""
Read a line of text from standard input and return the equivalent char;
Expand All @@ -49,6 +81,7 @@ def get_char(prompt=None):
if prompt is None:
print("Retry: ", end="")


def get_float(prompt=None):
"""
Read a line of text from standard input and return the equivalent float
Expand All @@ -69,20 +102,21 @@ def get_float(prompt=None):
if prompt is None:
print("Retry: ", end="")


def get_int(prompt=None):
"""
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
can't be read, return None.
"""
while True:
s = get_string(prompt);
s = get_string(prompt)
if s is 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
if type(i) is int: # could become long in Python 2
return i
except ValueError:
pass
Expand All @@ -91,6 +125,7 @@ def get_int(prompt=None):
if prompt is None:
print("Retry: ", end="")


if sys.version_info.major != 3:
def get_long(prompt=None):
"""
Expand All @@ -112,6 +147,7 @@ def get_long(prompt=None):
if prompt is None:
print("Retry: ", end="")


def get_string(prompt=None):
"""
Read a line of text from standard input and return it as a string,
Expand Down
8 changes: 6 additions & 2 deletions src/cs50/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import sys
import warnings


class SQL(object):
"""Wrap SQLAlchemy to provide a simple SQL API."""

Expand All @@ -23,7 +24,7 @@ def __init__(self, url, **kwargs):

# log statements to standard error
logging.basicConfig(level=logging.DEBUG)
self.logger = logging.getLogger(__name__)
self.logger = logging.getLogger("cs50")

# create engine, raising exception if back end's module not installed
self.engine = sqlalchemy.create_engine(url, **kwargs)
Expand All @@ -36,7 +37,9 @@ class UserDefinedType(sqlalchemy.TypeDecorator):
"""
Add support for expandable values, a la https://bitbucket.org/zzzeek/sqlalchemy/issues/3953/expanding-parameter.
"""

impl = sqlalchemy.types.UserDefinedType

def process_literal_param(self, value, dialect):
"""Receive a literal parameter value to be rendered inline within a statement."""
def process(value):
Expand Down Expand Up @@ -109,7 +112,8 @@ def process(value):

# bind parameters before statement reaches database, so that bound parameters appear in exceptions
# http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.text
statement = statement.bindparams(sqlalchemy.bindparam(key, value=value, type_=UserDefinedType()))
statement = statement.bindparams(sqlalchemy.bindparam(
key, value=value, type_=UserDefinedType()))

# stringify bound parameters
# http://docs.sqlalchemy.org/en/latest/faq/sqlexpressions.html#how-do-i-render-sql-expressions-as-strings-possibly-with-bound-parameters-inlined
Expand Down
6 changes: 6 additions & 0 deletions tests/tb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import cs50
import requests

def f():
res = requests.get("cs50.harvard.edu")
f()