From 186e9471127e656f61db474423fdb76dfd0c79c9 Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Sun, 16 Sep 2012 14:02:49 -0700 Subject: [PATCH] Remove tornado.database, which is now distributed separately. --- .travis.yml | 2 +- demos/blog/README | 6 +- demos/blog/blog.py | 6 +- maint/requirements.txt | 1 - maint/test/appengine/common/cgi_runtests.py | 4 +- maint/vm/ubuntu10.04/setup.sh | 2 - maint/vm/ubuntu10.04/tox.ini | 3 - maint/vm/ubuntu12.04/setup.sh | 2 - maint/vm/ubuntu12.04/tox.ini | 2 - tornado/database.py | 239 -------------------- tornado/test/import_test.py | 9 - tox.ini | 10 +- website/sphinx/database.rst | 5 - website/sphinx/integration.rst | 1 - website/sphinx/releases/next.rst | 2 + 15 files changed, 13 insertions(+), 281 deletions(-) delete mode 100644 tornado/database.py delete mode 100644 website/sphinx/database.rst diff --git a/.travis.yml b/.travis.yml index 47916bdb..126eefee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ matrix: install: - if [[ $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install --use-mirrors simplejson unittest2; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install --use-mirrors unittest2; fi - - if [[ $FULL == 'true' ]]; then sudo apt-get install librtmp-dev; pip install --use-mirrors MySQL-python pycurl; fi + - if [[ $FULL == 'true' ]]; then sudo apt-get install librtmp-dev; pip install --use-mirrors pycurl; fi - if [[ $FULL == 'true' && $TRAVIS_PYTHON_VERSION == '2.5' ]]; then pip install --use-mirrors twisted==11.0.0 'zope.interface<4.0'; fi - if [[ $FULL == 'true' && $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install --use-mirrors twisted==11.0.0; fi - if [[ $FULL == 'true' && $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install --use-mirrors twisted==12.0.0; fi diff --git a/demos/blog/README b/demos/blog/README index a033e7a1..5e413801 100644 --- a/demos/blog/README +++ b/demos/blog/README @@ -16,6 +16,10 @@ need to set up MySQL and the database schema for the demo to run. can run "apt-get install mysql". Under OS X you can download the MySQL PKG file from http://dev.mysql.com/downloads/mysql/ +3. Install Python prerequisites + + Install the packages MySQL-python and torndb (e.g. using pip or easy_install) + 3. Connect to MySQL and create a database and user for the blog. Connect to MySQL as a user that can create databases and users: @@ -51,7 +55,7 @@ need to set up MySQL and the database schema for the demo to run. authentication. Currently the first user to connect will automatically be given the - ability to create and edit posts. + ability to create and edit posts. Once you've created one blog post, subsequent users will not be prompted to sign in. diff --git a/demos/blog/blog.py b/demos/blog/blog.py index 14544a56..bff45c36 100755 --- a/demos/blog/blog.py +++ b/demos/blog/blog.py @@ -17,8 +17,8 @@ import markdown import os.path import re +import torndb import tornado.auth -import tornado.database import tornado.httpserver import tornado.ioloop import tornado.options @@ -58,7 +58,7 @@ class Application(tornado.web.Application): tornado.web.Application.__init__(self, handlers, **settings) # Have one global connection to the blog DB across all handlers - self.db = tornado.database.Connection( + self.db = torndb.Connection( host=options.mysql_host, database=options.mysql_database, user=options.mysql_user, password=options.mysql_password) @@ -152,7 +152,7 @@ class AuthLoginHandler(BaseHandler, tornado.auth.GoogleMixin): self.get_authenticated_user(self.async_callback(self._on_auth)) return self.authenticate_redirect() - + def _on_auth(self, user): if not user: raise tornado.web.HTTPError(500, "Google auth failed") diff --git a/maint/requirements.txt b/maint/requirements.txt index 8f9a90ce..e387759a 100644 --- a/maint/requirements.txt +++ b/maint/requirements.txt @@ -1,7 +1,6 @@ # Frozen pip requirements for tools used in the development of tornado # Tornado's optional dependencies -MySQL-python==1.2.3 Twisted==12.1.0 pycurl==7.19.0 diff --git a/maint/test/appengine/common/cgi_runtests.py b/maint/test/appengine/common/cgi_runtests.py index a3f1596b..d2b47490 100644 --- a/maint/test/appengine/common/cgi_runtests.py +++ b/maint/test/appengine/common/cgi_runtests.py @@ -33,7 +33,6 @@ def import_everything(): # import tornado.auth # import tornado.autoreload # import tornado.curl_httpclient # depends on pycurl - # import tornado.database # depends on MySQLdb import tornado.escape # import tornado.httpclient # import tornado.httpserver @@ -53,7 +52,7 @@ def import_everything(): import tornado.web # import tornado.websocket import tornado.wsgi - + def all(): return unittest.defaultTestLoader.loadTestsFromNames(TEST_MODULES) @@ -72,4 +71,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/maint/vm/ubuntu10.04/setup.sh b/maint/vm/ubuntu10.04/setup.sh index d5db904f..f54e3858 100644 --- a/maint/vm/ubuntu10.04/setup.sh +++ b/maint/vm/ubuntu10.04/setup.sh @@ -12,7 +12,6 @@ apt-get update APT_PACKAGES=" python-pip python-dev -libmysqlclient-dev libcurl4-openssl-dev python-software-properties " @@ -40,7 +39,6 @@ apt-get -y install $DEADSNAKES_PACKAGES PIP_PACKAGES=" virtualenv tox -MySQL-python pycurl twisted " diff --git a/maint/vm/ubuntu10.04/tox.ini b/maint/vm/ubuntu10.04/tox.ini index eeca8b41..e8cfea27 100644 --- a/maint/vm/ubuntu10.04/tox.ini +++ b/maint/vm/ubuntu10.04/tox.ini @@ -15,7 +15,6 @@ deps = [testenv:py25-full] basepython = python2.5 deps = - MySQL-python pycurl simplejson twisted==11.0.0 @@ -27,7 +26,6 @@ deps = unittest2 [testenv:py26-full] deps = - MySQL-python pycurl twisted==11.0.0 unittest2 @@ -35,6 +33,5 @@ deps = [testenv:py27-full] basepython = python2.7 deps = - MySQL-python pycurl twisted==11.0.0 diff --git a/maint/vm/ubuntu12.04/setup.sh b/maint/vm/ubuntu12.04/setup.sh index 67119e60..aba24fd3 100644 --- a/maint/vm/ubuntu12.04/setup.sh +++ b/maint/vm/ubuntu12.04/setup.sh @@ -12,7 +12,6 @@ apt-get update APT_PACKAGES=" python-pip python-dev -libmysqlclient-dev libcurl4-openssl-dev python-software-properties " @@ -38,7 +37,6 @@ apt-get -y install $DEADSNAKES_PACKAGES PIP_PACKAGES=" virtualenv tox -MySQL-python pycurl twisted " diff --git a/maint/vm/ubuntu12.04/tox.ini b/maint/vm/ubuntu12.04/tox.ini index 9e8a663d..48177476 100644 --- a/maint/vm/ubuntu12.04/tox.ini +++ b/maint/vm/ubuntu12.04/tox.ini @@ -15,7 +15,6 @@ deps = [testenv:py25-full] basepython = python2.5 deps = - MySQL-python pycurl simplejson twisted==11.0.0 @@ -29,6 +28,5 @@ deps = unittest2 [testenv:py27-full] basepython = python2.7 deps = - MySQL-python pycurl twisted==11.0.0 \ No newline at end of file diff --git a/tornado/database.py b/tornado/database.py deleted file mode 100644 index f680bc34..00000000 --- a/tornado/database.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2009 Facebook -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""A lightweight wrapper around MySQLdb.""" - -from __future__ import absolute_import, division, with_statement - -import copy -import itertools -import time - -from tornado.log import gen_log - -try: - import MySQLdb.constants - import MySQLdb.converters - import MySQLdb.cursors -except ImportError: - # If MySQLdb isn't available this module won't actually be useable, - # but we want it to at least be importable (mainly for readthedocs.org, - # which has limitations on third-party modules) - MySQLdb = None - - -class Connection(object): - """A lightweight wrapper around MySQLdb DB-API connections. - - The main value we provide is wrapping rows in a dict/object so that - columns can be accessed by name. Typical usage:: - - db = database.Connection("localhost", "mydatabase") - for article in db.query("SELECT * FROM articles"): - print article.title - - Cursors are hidden by the implementation, but other than that, the methods - are very similar to the DB-API. - - We explicitly set the timezone to UTC and the character encoding to - UTF-8 on all connections to avoid time zone and encoding errors. - """ - def __init__(self, host, database, user=None, password=None, - max_idle_time=7 * 3600): - self.host = host - self.database = database - self.max_idle_time = max_idle_time - - args = dict(conv=CONVERSIONS, use_unicode=True, charset="utf8", - db=database, init_command='SET time_zone = "+0:00"', - sql_mode="TRADITIONAL") - if user is not None: - args["user"] = user - if password is not None: - args["passwd"] = password - - # We accept a path to a MySQL socket file or a host(:port) string - if "/" in host: - args["unix_socket"] = host - else: - self.socket = None - pair = host.split(":") - if len(pair) == 2: - args["host"] = pair[0] - args["port"] = int(pair[1]) - else: - args["host"] = host - args["port"] = 3306 - - self._db = None - self._db_args = args - self._last_use_time = time.time() - try: - self.reconnect() - except Exception: - gen_log.error("Cannot connect to MySQL on %s", self.host, - exc_info=True) - - def __del__(self): - self.close() - - def close(self): - """Closes this database connection.""" - if getattr(self, "_db", None) is not None: - self._db.close() - self._db = None - - def reconnect(self): - """Closes the existing database connection and re-opens it.""" - self.close() - self._db = MySQLdb.connect(**self._db_args) - self._db.autocommit(True) - - def iter(self, query, *parameters): - """Returns an iterator for the given query and parameters.""" - self._ensure_connected() - cursor = MySQLdb.cursors.SSCursor(self._db) - try: - self._execute(cursor, query, parameters) - column_names = [d[0] for d in cursor.description] - for row in cursor: - yield Row(zip(column_names, row)) - finally: - cursor.close() - - def query(self, query, *parameters): - """Returns a row list for the given query and parameters.""" - cursor = self._cursor() - try: - self._execute(cursor, query, parameters) - column_names = [d[0] for d in cursor.description] - return [Row(itertools.izip(column_names, row)) for row in cursor] - finally: - cursor.close() - - def get(self, query, *parameters): - """Returns the first row returned for the given query.""" - rows = self.query(query, *parameters) - if not rows: - return None - elif len(rows) > 1: - raise Exception("Multiple rows returned for Database.get() query") - else: - return rows[0] - - # rowcount is a more reasonable default return value than lastrowid, - # but for historical compatibility execute() must return lastrowid. - def execute(self, query, *parameters): - """Executes the given query, returning the lastrowid from the query.""" - return self.execute_lastrowid(query, *parameters) - - def execute_lastrowid(self, query, *parameters): - """Executes the given query, returning the lastrowid from the query.""" - cursor = self._cursor() - try: - self._execute(cursor, query, parameters) - return cursor.lastrowid - finally: - cursor.close() - - def execute_rowcount(self, query, *parameters): - """Executes the given query, returning the rowcount from the query.""" - cursor = self._cursor() - try: - self._execute(cursor, query, parameters) - return cursor.rowcount - finally: - cursor.close() - - def executemany(self, query, parameters): - """Executes the given query against all the given param sequences. - - We return the lastrowid from the query. - """ - return self.executemany_lastrowid(query, parameters) - - def executemany_lastrowid(self, query, parameters): - """Executes the given query against all the given param sequences. - - We return the lastrowid from the query. - """ - cursor = self._cursor() - try: - cursor.executemany(query, parameters) - return cursor.lastrowid - finally: - cursor.close() - - def executemany_rowcount(self, query, parameters): - """Executes the given query against all the given param sequences. - - We return the rowcount from the query. - """ - cursor = self._cursor() - try: - cursor.executemany(query, parameters) - return cursor.rowcount - finally: - cursor.close() - - def _ensure_connected(self): - # Mysql by default closes client connections that are idle for - # 8 hours, but the client library does not report this fact until - # you try to perform a query and it fails. Protect against this - # case by preemptively closing and reopening the connection - # if it has been idle for too long (7 hours by default). - if (self._db is None or - (time.time() - self._last_use_time > self.max_idle_time)): - self.reconnect() - self._last_use_time = time.time() - - def _cursor(self): - self._ensure_connected() - return self._db.cursor() - - def _execute(self, cursor, query, parameters): - try: - return cursor.execute(query, parameters) - except OperationalError: - gen_log.error("Error connecting to MySQL on %s", self.host) - self.close() - raise - - -class Row(dict): - """A dict that allows for object-like property access syntax.""" - def __getattr__(self, name): - try: - return self[name] - except KeyError: - raise AttributeError(name) - -if MySQLdb is not None: - # Fix the access conversions to properly recognize unicode/binary - FIELD_TYPE = MySQLdb.constants.FIELD_TYPE - FLAG = MySQLdb.constants.FLAG - CONVERSIONS = copy.copy(MySQLdb.converters.conversions) - - field_types = [FIELD_TYPE.BLOB, FIELD_TYPE.STRING, FIELD_TYPE.VAR_STRING] - if 'VARCHAR' in vars(FIELD_TYPE): - field_types.append(FIELD_TYPE.VARCHAR) - - for field_type in field_types: - CONVERSIONS[field_type] = [(FLAG.BINARY, str)] + CONVERSIONS[field_type] - - # Alias some common MySQL exceptions - IntegrityError = MySQLdb.IntegrityError - OperationalError = MySQLdb.OperationalError diff --git a/tornado/test/import_test.py b/tornado/test/import_test.py index 97c2277b..f6a1673c 100644 --- a/tornado/test/import_test.py +++ b/tornado/test/import_test.py @@ -10,7 +10,6 @@ class ImportTest(unittest.TestCase): import tornado.auth import tornado.autoreload # import tornado.curl_httpclient # depends on pycurl - # import tornado.database # depends on MySQLdb import tornado.escape import tornado.httpclient import tornado.httpserver @@ -42,14 +41,6 @@ class ImportTest(unittest.TestCase): else: import tornado.curl_httpclient - def test_import_mysqldb(self): - try: - import MySQLdb - except ImportError: - pass - else: - import tornado.database - def test_import_twisted(self): try: import twisted diff --git a/tox.ini b/tox.ini index f4291e38..a735049d 100644 --- a/tox.ini +++ b/tox.ini @@ -7,9 +7,7 @@ # less thorough. # # On my macports-based setup, the environment variable -# ARCHFLAGS='-arch x86_64' must be set when building pycurl, and a -# symlink from mysql_config to mysql_config5 must exist when building -# MySQL-python. +# ARCHFLAGS='-arch x86_64' must be set when building pycurl. [tox] # "-full" variants include optional dependencies, to ensure # that things work both in a bare install and with all the extras. @@ -35,7 +33,6 @@ deps = [testenv:py25-full] basepython = python2.5 deps = - MySQL-python pycurl simplejson # twisted is dropping python 2.5 support in 12.2.0 @@ -53,7 +50,6 @@ deps = unittest2 [testenv:py26-full] basepython = python2.6 deps = - MySQL-python pycurl twisted==11.0.0 unittest2 @@ -61,7 +57,6 @@ deps = [testenv:py27-full] basepython = python2.7 deps = - MySQL-python pycurl twisted>=12.0.0 @@ -71,7 +66,6 @@ deps = # this flag controls which client all the other tests use. basepython = python2.7 deps = - MySQL-python pycurl twisted>=11.1.0 commands = python -m tornado.test.runtests --httpclient=tornado.curl_httpclient.CurlAsyncHTTPClient {posargs:} @@ -83,7 +77,6 @@ commands = python -m tornado.test.runtests --httpclient=tornado.curl_httpclient. # run this configuration there. basepython = pypy deps = - MySQL-python twisted>=12.1.0 # In python 3, opening files in text mode uses a system-dependent encoding by @@ -113,7 +106,6 @@ basepython = python3.3 [testenv:py27-opt] basepython = python2.7 deps = - MySQL-python pycurl twisted>=12.0.0 commands = python -O -m tornado.test.runtests {posargs:} diff --git a/website/sphinx/database.rst b/website/sphinx/database.rst deleted file mode 100644 index f6debdc9..00000000 --- a/website/sphinx/database.rst +++ /dev/null @@ -1,5 +0,0 @@ -``tornado.database`` --- Simple MySQL client wrapper -==================================================== - -.. automodule:: tornado.database - :members: diff --git a/website/sphinx/integration.rst b/website/sphinx/integration.rst index 1df2fa02..8bdcadae 100644 --- a/website/sphinx/integration.rst +++ b/website/sphinx/integration.rst @@ -4,7 +4,6 @@ Integration with other services .. toctree:: auth - database twisted websocket wsgi diff --git a/website/sphinx/releases/next.rst b/website/sphinx/releases/next.rst index e5f7ed04..788c1e2e 100644 --- a/website/sphinx/releases/next.rst +++ b/website/sphinx/releases/next.rst @@ -33,3 +33,5 @@ In progress * New function `tornado.testing.bind_unused_port` both chooses a port and binds a socket to it, so there is no risk of another process using the same port. ``get_unused_port`` is now deprecated. +* The `tornado.database` module has been removed. It is now available + as a separate package, `torndb `_