enable the cextension by default, falling back to pure python when the

extension fails to compile
fixes #2129
This commit is contained in:
Philip Jenvey 2011-04-13 18:32:15 -07:00
parent 74f2e214c4
commit a2094b1b6f
3 changed files with 208 additions and 165 deletions

View File

@ -91,6 +91,11 @@ CHANGES
will be coerced to integer. [ticket:2116]
(also in 0.6.7)
- engine
- The C extension is now enabled by default with a
fallback to pure python if it fails to compile.
[ticket:2129]
- schema
- The 'useexisting' flag on Table has been superceded
by a new pair of flags 'keep_existing' and

11
README
View File

@ -35,17 +35,6 @@ To install::
To use without installation, include the ``lib`` directory in your Python
path.
Installing the C extension
--------------------------
If installing with Setuptools or Distribute, the C extensions are built
and installed using the --with-cextensions flag:
python setup.py --with-cextensions install
If using plain Distutils, change the BUILD_CEXTENSIONS flag in setup.py
to "True".
Running Tests
-------------

357
setup.py
View File

@ -4,15 +4,12 @@ Please see README for basic installation instructions.
"""
# If using distutils (not distribute/setuptools),
# set this flag to True to compile C extensions.
# Otherwise use --with-cextensions
BUILD_CEXTENSIONS = False
import os
import re
import sys
from distutils.command.build_ext import build_ext
from distutils.errors import (CCompilerError, DistutilsExecError,
DistutilsPlatformError)
try:
from setuptools import setup, Extension, Feature
except ImportError:
@ -32,6 +29,7 @@ elif sys.version_info >= (3, 0):
extra.update(
use_2to3=True,
)
IS_PYPY = hasattr(sys, 'pypy_translation_info')
ext_modules = [
Extension('sqlalchemy.cprocessors',
@ -39,16 +37,34 @@ ext_modules = [
Extension('sqlalchemy.cresultproxy',
sources=['lib/sqlalchemy/cextension/resultproxy.c'])
]
if Feature:
extra.update(
features={'cextensions': Feature(
"optional C speed-enhancements",
standard=False,
ext_modules=ext_modules
)}
)
elif BUILD_CEXTENSIONS:
extra['ext_modules'] = 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)
else:
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
class BuildFailed(Exception):
def __init__(self, cause):
self.cause = cause
class ve_build_ext(build_ext):
# This class allows C extension building to fail.
def run(self):
try:
build_ext.run(self)
except DistutilsPlatformError, exc:
raise BuildFailed(exc)
def build_extension(self, ext):
try:
build_ext.build_extension(self, ext)
except ext_errors, exc:
raise BuildFailed(exc)
def find_packages(dir_):
packages = []
@ -65,149 +81,182 @@ VERSION = re.compile(r".*__version__ = '(.*?)'",
re.S).match(v.read()).group(1)
v.close()
setup(name="SQLAlchemy",
version=VERSION,
description="Database Abstraction Library",
author="Mike Bayer",
author_email="mike_mp@zzzcomputing.com",
url="http://www.sqlalchemy.org",
packages=find_packages('lib'),
package_dir={'': 'lib'},
license="MIT License",
def run_setup(with_cext):
kwargs = extra.copy()
if with_cext:
if Feature:
kwargs['features'] = {'cextensions': Feature(
"optional C speed-enhancements",
standard=True,
ext_modules=ext_modules
)}
else:
kwargs['ext_modules'] = ext_modules
tests_require=['nose >= 0.11'],
test_suite="sqla_nose",
setup(name="SQLAlchemy",
version=VERSION,
description="Database Abstraction Library",
author="Mike Bayer",
author_email="mike_mp@zzzcomputing.com",
url="http://www.sqlalchemy.org",
packages=find_packages('lib'),
package_dir={'': 'lib'},
license="MIT License",
cmdclass={'build_ext': ve_build_ext},
long_description="""\
SQLAlchemy is:
tests_require=['nose >= 0.11'],
test_suite="sqla_nose",
* The Python SQL toolkit and Object Relational Mapper
that gives application developers the full power and
flexibility of SQL. SQLAlchemy provides a full suite
of well known enterprise-level persistence patterns,
designed for efficient and high-performing database
access, adapted into a simple and Pythonic domain
language.
* extremely easy to use for all the basic tasks, such
as: accessing pooled connections, constructing SQL
from Python expressions, finding object instances, and
commiting object modifications back to the database.
* powerful enough for complicated tasks, such as: eager
load a graph of objects and their dependencies via
joins; map recursive adjacency structures
automatically; map objects to not just tables but to
any arbitrary join or select statement; combine
multiple tables together to load whole sets of
otherwise unrelated objects from a single result set;
commit entire graphs of object changes in one step.
* built to conform to what DBAs demand, including the
ability to swap out generated SQL with hand-optimized
statements, full usage of bind parameters for all
literal values, fully transactionalized and consistent
updates using Unit of Work.
* modular. Different parts of SQLAlchemy can be used
independently of the rest, including the connection
pool, SQL construction, and ORM. SQLAlchemy is
constructed in an open style that allows plenty of
customization, with an architecture that supports
custom datatypes, custom SQL extensions, and ORM
plugins which can augment or extend mapping
functionality.
long_description="""\
SQLAlchemy is:
SQLAlchemy's Philosophy:
* The Python SQL toolkit and Object Relational Mapper
that gives application developers the full power and
flexibility of SQL. SQLAlchemy provides a full suite
of well known enterprise-level persistence patterns,
designed for efficient and high-performing database
access, adapted into a simple and Pythonic domain
language.
* extremely easy to use for all the basic tasks, such
as: accessing pooled connections, constructing SQL
from Python expressions, finding object instances, and
commiting object modifications back to the database.
* powerful enough for complicated tasks, such as: eager
load a graph of objects and their dependencies via
joins; map recursive adjacency structures
automatically; map objects to not just tables but to
any arbitrary join or select statement; combine
multiple tables together to load whole sets of
otherwise unrelated objects from a single result set;
commit entire graphs of object changes in one step.
* built to conform to what DBAs demand, including the
ability to swap out generated SQL with hand-optimized
statements, full usage of bind parameters for all
literal values, fully transactionalized and consistent
updates using Unit of Work.
* modular. Different parts of SQLAlchemy can be used
independently of the rest, including the connection
pool, SQL construction, and ORM. SQLAlchemy is
constructed in an open style that allows plenty of
customization, with an architecture that supports
custom datatypes, custom SQL extensions, and ORM
plugins which can augment or extend mapping
functionality.
* SQL databases behave less and less like object
collections the more size and performance start to
matter; object collections behave less and less like
tables and rows the more abstraction starts to matter.
SQLAlchemy aims to accomodate both of these
principles.
* Your classes aren't tables, and your objects aren't
rows. Databases aren't just collections of tables;
they're relational algebra engines. You don't have to
select from just tables, you can select from joins,
subqueries, and unions. Database and domain concepts
should be visibly decoupled from the beginning,
allowing both sides to develop to their full
potential.
* For example, table metadata (objects that describe
tables) are declared distinctly from the classes
theyre designed to store. That way database
relationship concepts don't interfere with your object
design concepts, and vice-versa; the transition from
table-mapping to selectable-mapping is seamless; a
class can be mapped against the database in more than
one way. SQLAlchemy provides a powerful mapping layer
that can work as automatically or as manually as you
choose, determining relationships based on foreign
keys or letting you define the join conditions
explicitly, to bridge the gap between database and
domain.
SQLAlchemy's Philosophy:
SQLAlchemy's Advantages:
* SQL databases behave less and less like object
collections the more size and performance start to
matter; object collections behave less and less like
tables and rows the more abstraction starts to matter.
SQLAlchemy aims to accomodate both of these
principles.
* Your classes aren't tables, and your objects aren't
rows. Databases aren't just collections of tables;
they're relational algebra engines. You don't have to
select from just tables, you can select from joins,
subqueries, and unions. Database and domain concepts
should be visibly decoupled from the beginning,
allowing both sides to develop to their full
potential.
* For example, table metadata (objects that describe
tables) are declared distinctly from the classes
theyre designed to store. That way database
relationship concepts don't interfere with your object
design concepts, and vice-versa; the transition from
table-mapping to selectable-mapping is seamless; a
class can be mapped against the database in more than
one way. SQLAlchemy provides a powerful mapping layer
that can work as automatically or as manually as you
choose, determining relationships based on foreign
keys or letting you define the join conditions
explicitly, to bridge the gap between database and
domain.
* The Unit Of Work system organizes pending CRUD
operations into queues and commits them all in one
batch. It then performs a topological "dependency
sort" of all items to be committed and deleted and
groups redundant statements together. This produces
the maxiumum efficiency and transaction safety, and
minimizes chances of deadlocks. Modeled after Fowler's
"Unit of Work" pattern as well as Java Hibernate.
* Function-based query construction allows boolean
expressions, operators, functions, table aliases,
selectable subqueries, create/update/insert/delete
queries, correlated updates, correlated EXISTS
clauses, UNION clauses, inner and outer joins, bind
parameters, free mixing of literal text within
expressions, as little or as much as desired.
Query-compilation is vendor-specific; the same query
object can be compiled into any number of resulting
SQL strings depending on its compilation algorithm.
* Database mapping and class design are totally
separate. Persisted objects have no subclassing
requirement (other than 'object') and are POPO's :
plain old Python objects. They retain serializability
(pickling) for usage in various caching systems and
session objects. SQLAlchemy "decorates" classes with
non-intrusive property accessors to automatically log
object creates and modifications with the UnitOfWork
engine, to lazyload related data, as well as to track
attribute change histories.
* Custom list classes can be used with eagerly or lazily
loaded child object lists, allowing rich relationships
to be created on the fly as SQLAlchemy appends child
objects to an object attribute.
* Composite (multiple-column) primary keys are
supported, as are "association" objects that represent
the middle of a "many-to-many" relationship.
* Self-referential tables and mappers are supported.
Adjacency list structures can be created, saved, and
deleted with proper cascading, with no extra
programming.
* Data mapping can be used in a row-based manner. Any
bizarre hyper-optimized query that you or your DBA can
cook up, you can run in SQLAlchemy, and as long as it
returns the expected columns within a rowset, you can
get your objects from it. For a rowset that contains
more than one kind of object per row, multiple mappers
can be chained together to return multiple object
instance lists from a single database round trip.
* The type system allows pre- and post- processing of
data, both at the bind parameter and the result set
level. User-defined types can be freely mixed with
built-in types. Generic types as well as SQL-specific
types are available.
SQLAlchemy's Advantages:
""",
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Topic :: Database :: Front-Ends",
"Operating System :: OS Independent",
],
**extra
)
* The Unit Of Work system organizes pending CRUD
operations into queues and commits them all in one
batch. It then performs a topological "dependency
sort" of all items to be committed and deleted and
groups redundant statements together. This produces
the maxiumum efficiency and transaction safety, and
minimizes chances of deadlocks. Modeled after Fowler's
"Unit of Work" pattern as well as Java Hibernate.
* Function-based query construction allows boolean
expressions, operators, functions, table aliases,
selectable subqueries, create/update/insert/delete
queries, correlated updates, correlated EXISTS
clauses, UNION clauses, inner and outer joins, bind
parameters, free mixing of literal text within
expressions, as little or as much as desired.
Query-compilation is vendor-specific; the same query
object can be compiled into any number of resulting
SQL strings depending on its compilation algorithm.
* Database mapping and class design are totally
separate. Persisted objects have no subclassing
requirement (other than 'object') and are POPO's :
plain old Python objects. They retain serializability
(pickling) for usage in various caching systems and
session objects. SQLAlchemy "decorates" classes with
non-intrusive property accessors to automatically log
object creates and modifications with the UnitOfWork
engine, to lazyload related data, as well as to track
attribute change histories.
* Custom list classes can be used with eagerly or lazily
loaded child object lists, allowing rich relationships
to be created on the fly as SQLAlchemy appends child
objects to an object attribute.
* Composite (multiple-column) primary keys are
supported, as are "association" objects that represent
the middle of a "many-to-many" relationship.
* Self-referential tables and mappers are supported.
Adjacency list structures can be created, saved, and
deleted with proper cascading, with no extra
programming.
* Data mapping can be used in a row-based manner. Any
bizarre hyper-optimized query that you or your DBA can
cook up, you can run in SQLAlchemy, and as long as it
returns the expected columns within a rowset, you can
get your objects from it. For a rowset that contains
more than one kind of object per row, multiple mappers
can be chained together to return multiple object
instance lists from a single database round trip.
* The type system allows pre- and post- processing of
data, both at the bind parameter and the result set
level. User-defined types can be freely mixed with
built-in types. Generic types as well as SQL-specific
types are available.
""",
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Topic :: Database :: Front-Ends",
"Operating System :: OS Independent",
],
**kwargs
)
try:
# Likely don't want the cextension built on PyPy+CPyExt
run_setup(not IS_PYPY)
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
run_setup(False)
print '*' * 75
print BUILD_EXT_WARNING
print "Plain-Python installation succeeded."
print '*' * 75