From: Mike Bayer Date: Sun, 17 Apr 2011 17:22:33 +0000 (-0400) Subject: - rework setup.py script to work with: X-Git-Tag: rel_0_7b4~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fcded554dfbb102ee6c34982e3449592718ba921;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - rework setup.py script to work with: - Python 3 - Python 3 builds if Distribute isn't installed - rework install documentation again - raise if doc build with mako < 0.4.1 - Python 3.1 builds force doctest parse but then fails due to distribute bug, so remove usage of backslash \\ in hybrid.py docstring - put in the latest ez_setup.py --- diff --git a/doc/build/builder/builders.py b/doc/build/builder/builders.py index a93b839d56..c965650249 100644 --- a/doc/build/builder/builders.py +++ b/doc/build/builder/builders.py @@ -10,6 +10,11 @@ from pygments.formatters import HtmlFormatter, LatexFormatter import re from mako.lookup import TemplateLookup from mako.template import Template +from mako import __version__ + +if __version__ < "0.4.1": + raise Exception("Mako 0.4.1 or greater is required for " + "documentation build.") class MakoBridge(TemplateBridge): def init(self, builder, *args, **kw): diff --git a/doc/build/intro.rst b/doc/build/intro.rst index 0fa49ac0a9..7d741341bc 100644 --- a/doc/build/intro.rst +++ b/doc/build/intro.rst @@ -31,7 +31,8 @@ queries. Documentation Overview ====================== -The documentation is separated into three sections: :ref:`orm_toplevel`, :ref:`core_toplevel`, and :ref:`dialect_toplevel`. +The documentation is separated into three sections: :ref:`orm_toplevel`, +:ref:`core_toplevel`, and :ref:`dialect_toplevel`. In :ref:`orm_toplevel`, the Object Relational Mapper is introduced and fully described. New users should begin with the :ref:`ormtutorial_toplevel`. If you @@ -40,11 +41,12 @@ as well as management of Python objects, proceed to this tutorial. In :ref:`core_toplevel`, the breadth of SQLAlchemy's SQL and database integration and description services are documented, the core of which is the -SQL Expression language. The SQL Expression Language is a toolkit all its own, independent of the ORM package, which can be used to construct manipulable SQL +SQL Expression language. The SQL Expression Language is a toolkit all its own, +independent of the ORM package, which can be used to construct manipulable SQL expressions which can be programmatically constructed, modified, and executed, -returning cursor-like result sets. In contrast to the ORM's domain-centric +returning cursor-like result sets. In contrast to the ORM's domain-centric mode of usage, the expression language provides a schema-centric usage -paradigm. New users should begin here with :ref:`sqlexpression_toplevel`. +paradigm. New users should begin here with :ref:`sqlexpression_toplevel`. SQLAlchemy engine, connection, and pooling services are also described in :ref:`core_toplevel`. @@ -60,31 +62,54 @@ applications is at :ref:`examples_toplevel`. There is also a wide variety of examples involving both core SQLAlchemy constructs as well as the ORM on the wiki. See -``_. +`Theatrum Chemicum `_. .. _installation: Installation Guide ================== -SQLAlchemy builds using the standard `Python Distutils `_ approach. +Supported Platforms +------------------- -Installing with setuptools or pip ----------------------------------- +SQLAlchemy has been tested against the following platforms: + +* cPython since version 2.4, through the 2.xx series +* cPython version 3, throughout all 3.xx series +* `Jython `_ 2.5 or greater +* `Pypy `_ 1.5 or greater + +Supported Installation Methods +------------------------------- + +SQLAlchemy supports installation using standard Python "distutils" or +"setuptools" methodologies. An overview of potential setups is as follows: -Installing SQLAlchemy from scratch is most easily achieved with `setuptools -`_, or alternatively -`pip `_. Assuming it's installed, just run this from the command-line: +* **Plain Python Distutils** - SQLAlchemy can be installed with a clean + Python install using the services provided via `Python Distutils `_, + using the ``setup.py`` script. The C extensions as well as Python 3 builds are supported. +* **Standard Setuptools** - When using `setuptools `_, + SQLAlchemy can be installed via ``setup.py`` or ``easy_install``, and the C + extensions are supported. setuptools is not supported on Python 3 at the time + of of this writing. +* **Distribute** - With `distribute `_, + SQLAlchemy can be installed via ``setup.py`` or ``easy_install``, and the C + extensions as well as Python 3 builds are supported. +* **pip** - `pip `_ is an installer that + rides on top of ``setuptools`` or ``distribute``, replacing the usage + of ``easy_install``. It is often preferred for its simpler mode of usage. -.. sourcecode:: none +Install via easy_install or pip +------------------------------- - # easy_install SQLAlchemy +When ``easy_install`` or ``pip`` is available, the distribution can be +downloaded from Pypi and installed in one step:: -Or with pip: + easy_install SQLAlchemy -.. sourcecode:: none +Or with pip:: - # pip install SQLAlchemy + pip install SQLAlchemy This command will download the latest version of SQLAlchemy from the `Python Cheese Shop `_ and install it to your system. @@ -92,33 +117,50 @@ Cheese Shop `_ and install it to your sy Installing using setup.py ---------------------------------- -Otherwise, you can install from the distribution using the ``setup.py`` script: +Otherwise, you can install from the distribution using the ``setup.py`` script:: -.. sourcecode:: none - - # python setup.py install + python setup.py install Installing the C Extensions ---------------------------------- -SQLAlchemy includes C extensions which provide an extra speed boost for dealing with result sets. These extensions build automatically when the build or install commands of setup.py are invoked. If the C extensions cannot be built, the setup process will output a warning message. +SQLAlchemy includes C extensions which provide an extra speed boost for +dealing with result sets. Currently, the extensions are only supported on the +2.xx series of cPython, not Python 3 or Pypy. + +setup.py will automatically build the extensions if an appropriate platform is +detected. If the build of the C extensions fails, due to missing compiler or +other issue, the setup process will output a warning message, and re-run the +build without the C extensions, upon completion reporting final status. + +To run the build/install without even attempting to compile the C extensions, +pass the flag ``--without-cextensions`` to the ``setup.py`` script:: -To disable building the C extensions, pass the flag ``--with-no-cextensions`` to the ``setup.py`` script. + python setup.py --without-cextensions install Installing on Python 3 ---------------------------------- -SQLAlchemy ships as Python 2 code. For Python 3 usage, the ``setup.py`` script will invoke the Python ``2to3`` tool on the build, plugging in an extra "preprocessor" as well. Using the Python 3 interpreter with ``setup.py`` or a Python 3 version of easy_install or pip is all that's needed. +SQLAlchemy ships as Python 2 code. For Python 3 usage, the ``setup.py`` script +will invoke the Python ``2to3`` tool on the build, plugging in an extra +"preprocessor" as well. The 2to3 step works with Python distutils +(part of the standard Python install) and Distribute - it will **not** +work with a non-Distribute setuptools installation. Installing a Database API ---------------------------------- -SQLAlchemy is designed to operate with a `DB-API `_ implementation built for a particular database, and includes support for the most popular databases. The current list is at :ref:`supported_dbapis`. +SQLAlchemy is designed to operate with a `DB-API +`_ implementation built for a +particular database, and includes support for the most popular databases. The +current list is at :ref:`supported_dbapis`. Checking the Installed SQLAlchemy Version ------------------------------------------ -This documentation covers SQLAlchemy version 0.7. If you're working on a system that already has SQLAlchemy installed, check the version from your Python prompt like this: +This documentation covers SQLAlchemy version 0.7. If you're working on a +system that already has SQLAlchemy installed, check the version from your +Python prompt like this: .. sourcecode:: python+sql @@ -131,4 +173,5 @@ This documentation covers SQLAlchemy version 0.7. If you're working on a system 0.6 to 0.7 Migration ===================== -Notes on what's changed from 0.6 to 0.7 is available on the SQLAlchemy wiki at `07Migration `_. +Notes on what's changed from 0.6 to 0.7 is available on the SQLAlchemy wiki at +`07Migration `_. diff --git a/ez_setup.py b/ez_setup.py index e33744ba1c..b74adc0654 100644 --- a/ez_setup.py +++ b/ez_setup.py @@ -14,7 +14,7 @@ the appropriate options to ``use_setuptools()``. This file can also be run as a script to install or upgrade setuptools. """ import sys -DEFAULT_VERSION = "0.6c9" +DEFAULT_VERSION = "0.6c11" DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3] md5_data = { @@ -28,6 +28,14 @@ md5_data = { 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', + 'setuptools-0.6c10-py2.3.egg': 'ce1e2ab5d3a0256456d9fc13800a7090', + 'setuptools-0.6c10-py2.4.egg': '57d6d9d6e9b80772c59a53a8433a5dd4', + 'setuptools-0.6c10-py2.5.egg': 'de46ac8b1c97c895572e5e8596aeb8c7', + 'setuptools-0.6c10-py2.6.egg': '58ea40aef06da02ce641495523a0b7f5', + 'setuptools-0.6c11-py2.3.egg': '2baeac6e13d414a9d28e7ba5b5a596de', + 'setuptools-0.6c11-py2.4.egg': 'bd639f9b0eac4c42497034dec2ec0c2b', + 'setuptools-0.6c11-py2.5.egg': '64c94f3bf7a72a13ec83e0b24f2749b2', + 'setuptools-0.6c11-py2.6.egg': 'bfa92100bd772d5a213eedd356d64086', 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', @@ -92,7 +100,7 @@ def use_setuptools( try: import pkg_resources except ImportError: - return do_download() + return do_download() try: pkg_resources.require("setuptools>="+version); return except pkg_resources.VersionConflict, e: @@ -104,11 +112,11 @@ def use_setuptools( "\n\n(Currently using %r)" ) % (version, e.args[0]) sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return do_download() except pkg_resources.DistributionNotFound: - return do_download() + pass + + del pkg_resources, sys.modules['pkg_resources'] # reload ok + return do_download() def download_setuptools( version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, diff --git a/lib/sqlalchemy/ext/hybrid.py b/lib/sqlalchemy/ext/hybrid.py index 136d7d506e..c16c38b2cf 100644 --- a/lib/sqlalchemy/ext/hybrid.py +++ b/lib/sqlalchemy/ext/hybrid.py @@ -104,7 +104,7 @@ SQL expression-level boolean behavior:: FROM interval WHERE interval.start <= :start_1 AND interval."end" > :end_1 - >>> ia = aliased(Interval) + >>> ia = aliased(Interval) >>> print Session().query(Interval, ia).filter(Interval.intersects(ia)) SELECT interval.id AS interval_id, interval.start AS interval_start, interval."end" AS interval_end, interval_1.id AS interval_1_id, @@ -240,8 +240,8 @@ is even present, this issue expresses itself differently at the SQL expression l would use an outer join:: >>> from sqlalchemy import or_ - >>> print Session().query(User, User.balance).outerjoin(User.accounts).\\ - ... filter(or_(User.balance < 5000, User.balance == None)) + >>> print (Session().query(User, User.balance).outerjoin(User.accounts). + ... filter(or_(User.balance < 5000, User.balance == None))) SELECT "user".id AS user_id, "user".name AS user_name, account.balance AS account_balance FROM "user" LEFT OUTER JOIN account ON "user".id = account.user_id WHERE account.balance < :balance_1 OR account.balance IS NULL diff --git a/setup.py b/setup.py index 6dcdd83455..ff82bc4553 100644 --- a/setup.py +++ b/setup.py @@ -12,10 +12,17 @@ from distutils.errors import (CCompilerError, DistutilsExecError, DistutilsPlatformError) try: from setuptools import setup, Extension, Feature + has_setuptools = True except ImportError: + has_setuptools = False from distutils.core import setup, Extension Feature = None + try: # Python 3 + from distutils.command.build_py import build_py_2to3 as build_py + except ImportError: # Python 2 + from distutils.command.build_py import build_py +cmdclass = {} pypy = hasattr(sys, 'pypy_version_info') py3k = False extra = {} @@ -29,9 +36,12 @@ elif sys.version_info >= (3, 0): from lib2to3.refactor import RefactoringTool RefactoringTool.refactor_string = refactor_string - extra.update( - use_2to3=True, - ) + if has_setuptools: + extra.update( + use_2to3=True, + ) + else: + cmdclass['build_py'] = build_py ext_modules = [ Extension('sqlalchemy.cprocessors', @@ -43,15 +53,16 @@ ext_modules = [ if sys.platform == 'win32' and sys.version_info > (2, 6): # 2.6's distutils.msvc9compiler can raise an IOError when failing to # find the compiler - ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError, - IOError) + ext_errors = ( + CCompilerError, DistutilsExecError, + DistutilsPlatformError, IOError) else: ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError) class BuildFailed(Exception): - def __init__(self, cause): - self.cause = cause + def __init__(self): + self.cause = sys.exc_info()[1] # work around py 2/3 different syntax class ve_build_ext(build_ext): # This class allows C extension building to fail. @@ -59,26 +70,36 @@ class ve_build_ext(build_ext): def run(self): try: build_ext.run(self) - except DistutilsPlatformError, exc: - raise BuildFailed(exc) + except DistutilsPlatformError: + raise BuildFailed() def build_extension(self, ext): try: build_ext.build_extension(self, ext) - except ext_errors, exc: - raise BuildFailed(exc) + except ext_errors: + raise BuildFailed() + +cmdclass['build_ext'] = ve_build_ext + +def status_msgs(*msgs): + print('*' * 75) + for msg in msgs: + print(msg) + print('*' * 75) def find_packages(dir_): packages = [] for pkg in ['sqlalchemy']: - for _dir, subdirectories, files in os.walk(os.path.join(dir_, pkg)): + for _dir, subdirectories, files in ( + os.walk(os.path.join(dir_, pkg)) + ): if '__init__.py' in files: lib, fragment = _dir.split(os.sep, 1) packages.append(fragment.replace(os.sep, '.')) return packages -v = open(os.path.join(os.path.dirname(__file__), 'lib', 'sqlalchemy', - '__init__.py')) +v = open(os.path.join(os.path.dirname(__file__), + 'lib', 'sqlalchemy', '__init__.py')) VERSION = re.compile(r".*__version__ = '(.*?)'", re.S).match(v.read()).group(1) v.close() @@ -104,7 +125,7 @@ def run_setup(with_cext): packages=find_packages('lib'), package_dir={'': 'lib'}, license="MIT License", - cmdclass={'build_ext': ve_build_ext}, + cmdclass=cmdclass, tests_require=['nose >= 0.11'], test_suite="sqla_nose", @@ -243,22 +264,30 @@ def run_setup(with_cext): **kwargs ) -try: - # Likely don't want the cextension built on PyPy+CPyExt - run_setup(not (pypy or py3k)) -except BuildFailed, exc: - print '*' * 75 - print exc.cause - BUILD_EXT_WARNING = "WARNING: The C extension could not be compiled, speedups are not enabled." - print '*' * 75 - print BUILD_EXT_WARNING - print "Failure information, if any, is above." - print "Retrying the build without the C extension now." - print '*' * 75 - +if pypy or py3k: run_setup(False) + status_msgs( + "WARNING: C extensions are not supported on " + + "this Python platform, speedups are not enabled.", + "Plain-Python build succeeded." + ) +else: + try: + run_setup(True) + except BuildFailed: + exc = sys.exc_info()[1] # work around py 2/3 different syntax + status_msgs( + exc.cause, + "WARNING: The C extension could not be compiled, " + + "speedups are not enabled.", + "Failure information, if any, is above.", + "Retrying the build without the C extension now." + ) + + run_setup(False) - print '*' * 75 - print BUILD_EXT_WARNING - print "Plain-Python installation succeeded." - print '*' * 75 + status_msgs( + "WARNING: The C extension could not be compiled, " + + "speedups are not enabled.", + "Plain-Python build succeeded." + )