BUG: Fix str/unicode warnings from SQLAlchemy on python 2.

When running with `reset_db=True` on python 2, several SQLAlchemy operations
were performed with bytes where unicode was expected, resulting in
warnings like the following.

```
/home/ssanderson/.virtualenvs/jupyterhub/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py:573:
SAWarning: Unicode type received non-unicodebind param value.
  param.append(processors[key](compiled_params[key]))
```

Fixes a few stray non-unicode literals and adds a unicode safe wrapper
for `getpass.getuser`.
This commit is contained in:
Scott Sanderson
2014-10-25 17:46:25 -04:00
parent fa7250ecc3
commit a34d514d66
3 changed files with 20 additions and 10 deletions

View File

@@ -4,7 +4,6 @@
# Copyright (c) IPython Development Team. # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import getpass
import io import io
import logging import logging
import os import os
@@ -41,7 +40,7 @@ from . import orm
from ._data import DATA_FILES_PATH from ._data import DATA_FILES_PATH
from .utils import ( from .utils import (
url_path_join, random_hex, TimeoutError, url_path_join, random_hex, TimeoutError,
ISO8601_ms, ISO8601_s, ISO8601_ms, ISO8601_s, getuser_unicode,
) )
# classes for config # classes for config
from .auth import Authenticator, PAMAuthenticator from .auth import Authenticator, PAMAuthenticator
@@ -353,7 +352,7 @@ class JupyterHubApp(Application):
"""More informative log messages for failed filesystem access""" """More informative log messages for failed filesystem access"""
path = os.path.abspath(path) path = os.path.abspath(path)
parent, fname = os.path.split(path) parent, fname = os.path.split(path)
user = getpass.getuser() user = getuser_unicode()
if not os.path.isdir(parent): if not os.path.isdir(parent):
self.log.error("Directory %s does not exist", parent) self.log.error("Directory %s does not exist", parent)
if os.path.exists(parent) and not os.access(parent, os.W_OK): if os.path.exists(parent) and not os.access(parent, os.W_OK):
@@ -385,7 +384,7 @@ class JupyterHubApp(Application):
port=self.hub_port, port=self.hub_port,
base_url=self.hub_prefix, base_url=self.hub_prefix,
cookie_secret=self.cookie_secret, cookie_secret=self.cookie_secret,
cookie_name='jupyter-hub-token', cookie_name=u'jupyter-hub-token',
) )
) )
self.db.add(self.hub) self.db.add(self.hub)
@@ -400,13 +399,13 @@ class JupyterHubApp(Application):
def init_users(self): def init_users(self):
"""Load users into and from the database""" """Load users into and from the database"""
db = self.db db = self.db
if not self.admin_users: if not self.admin_users:
# add current user as admin if there aren't any others # add current user as admin if there aren't any others
admins = db.query(orm.User).filter(orm.User.admin==True) admins = db.query(orm.User).filter(orm.User.admin==True)
if admins.first() is None: if admins.first() is None:
self.admin_users.add(getpass.getuser()) self.admin_users.add(getuser_unicode())
for name in self.admin_users: for name in self.admin_users:
# ensure anyone specified as admin in config is admin in db # ensure anyone specified as admin in config is admin in db
user = orm.User.find(db, name) user = orm.User.find(db, name)
@@ -511,7 +510,7 @@ class JupyterHubApp(Application):
self.proxy.public_server.port = self.port self.proxy.public_server.port = self.port
self.proxy.api_server.ip = self.proxy_api_ip self.proxy.api_server.ip = self.proxy_api_ip
self.proxy.api_server.port = self.proxy_api_port self.proxy.api_server.port = self.proxy_api_port
self.proxy.api_server.base_url = '/api/routes/' self.proxy.api_server.base_url = u'/api/routes/'
if self.proxy.auth_token is None: if self.proxy.auth_token is None:
self.proxy.auth_token = self.proxy_auth_token self.proxy.auth_token = self.proxy_auth_token
self.db.commit() self.db.commit()

View File

@@ -3,13 +3,13 @@
# Copyright (c) Jupyter Development Team. # Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import getpass
import logging import logging
from pytest import fixture from pytest import fixture
from tornado import ioloop from tornado import ioloop
from .. import orm from .. import orm
from ..utils import getuser_unicode
from .mocking import MockHubApp from .mocking import MockHubApp
@@ -24,7 +24,7 @@ def db():
if _db is None: if _db is None:
_db = orm.new_session('sqlite:///:memory:', echo=True) _db = orm.new_session('sqlite:///:memory:', echo=True)
user = orm.User( user = orm.User(
name=getpass.getuser(), name=getuser_unicode(),
server=orm.Server(), server=orm.Server(),
) )
hub = orm.Hub( hub = orm.Hub(

View File

@@ -4,9 +4,12 @@
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
import binascii import binascii
import getpass
import errno import errno
import os import os
import socket import socket
from six import text_type
from tornado import web, gen, ioloop from tornado import web, gen, ioloop
from tornado.httpclient import AsyncHTTPClient, HTTPError from tornado.httpclient import AsyncHTTPClient, HTTPError
from tornado.log import app_log from tornado.log import app_log
@@ -21,6 +24,14 @@ except NameError:
class TimeoutError(Exception): class TimeoutError(Exception):
pass pass
def getuser_unicode():
"""
Call getpass.getuser, ensuring that the output is returned as unicode.
"""
return text_type(getpass.getuser())
def random_port(): def random_port():
"""get a single random port""" """get a single random port"""
sock = socket.socket() sock = socket.socket()