diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-01-02 14:23:42 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-01-02 14:23:42 -0500 |
| commit | 350aed3fdb9f1e73e69655e53f44ca6a91c196da (patch) | |
| tree | 3d2a128667b5f6ca6d0b4e1f4865fc98aac6b60b /doc | |
| parent | 71f92436bdc86f30e2c21d8f5244733601e8c39e (diff) | |
| download | sqlalchemy-350aed3fdb9f1e73e69655e53f44ca6a91c196da.tar.gz | |
- whitespace removal bonanza
Diffstat (limited to 'doc')
26 files changed, 184 insertions, 187 deletions
diff --git a/doc/build/builder/builders.py b/doc/build/builder/builders.py index b82480ad3..d5feaf85e 100644 --- a/doc/build/builder/builders.py +++ b/doc/build/builder/builders.py @@ -14,14 +14,14 @@ from mako.template import Template class MakoBridge(TemplateBridge): def init(self, builder, *args, **kw): self.layout = builder.config.html_context.get('mako_layout', 'html') - + self.lookup = TemplateLookup(directories=builder.config.templates_path, format_exceptions=True, imports=[ "from builder import util" ] ) - + def render(self, template, context): template = template.replace(".html", ".mako") context['prevtopic'] = context.pop('prev', None) @@ -30,8 +30,8 @@ class MakoBridge(TemplateBridge): # sphinx 1.0b2 doesn't seem to be providing _ for some reason... context.setdefault('_', lambda x:x) return self.lookup.get_template(template).render_unicode(**context) - - + + def render_string(self, template, context): context['prevtopic'] = context.pop('prev', None) context['nexttopic'] = context.pop('next', None) @@ -44,7 +44,7 @@ class MakoBridge(TemplateBridge): "from builder import util" ] ).render_unicode(**context) - + class StripDocTestFilter(Filter): def filter(self, lexer, stream): for ttype, value in stream: @@ -116,7 +116,7 @@ def _strip_trailing_whitespace(iter_): buf[-1] = (buf[-1][0], buf[-1][1].rstrip()) for t, v in buf: yield t, v - + class PopupSQLFormatter(HtmlFormatter): def _format_lines(self, tokensource): buf = [] @@ -134,7 +134,7 @@ class PopupSQLFormatter(HtmlFormatter): yield 1, "<div class='popup_sql'>%s</div>" % re.sub(r'(?:[{stop}|\n]*)$', '', value) else: buf.append((ttype, value)) - + for t, v in _strip_trailing_whitespace(HtmlFormatter._format_lines(self, iter(buf))): yield t, v @@ -148,7 +148,7 @@ class PopupLatexFormatter(LatexFormatter): continue else: yield ttype, value - + def format(self, tokensource, outfile): LatexFormatter.format(self, self._filter_tokens(tokensource), outfile) @@ -164,5 +164,4 @@ def setup(app): app.connect('autodoc-skip-member', autodoc_skip_member) PygmentsBridge.html_formatter = PopupSQLFormatter PygmentsBridge.latex_formatter = PopupLatexFormatter - -
\ No newline at end of file + diff --git a/doc/build/builder/util.py b/doc/build/builder/util.py index dc2e27245..a9dcff001 100644 --- a/doc/build/builder/util.py +++ b/doc/build/builder/util.py @@ -6,7 +6,7 @@ def striptags(text): def go(m): # .html with no anchor if present, otherwise "#" for top of page return m.group(1) or '#' - + def strip_toplevel_anchors(text): return re.compile(r'(\.html)?#[-\w]+-toplevel').sub(go, text) - + diff --git a/doc/build/core/connections.rst b/doc/build/core/connections.rst index 7591e73e2..7b2e6aa69 100644 --- a/doc/build/core/connections.rst +++ b/doc/build/core/connections.rst @@ -22,7 +22,7 @@ Recall from :ref:`engines_toplevel` that an :class:`.Engine` is created via the :func:`.create_engine` call:: engine = create_engine('mysql://scott:tiger@localhost/test') - + The typical usage of :func:`.create_engine()` is once per particular database URL, held globally for the lifetime of a single application process. A single :class:`.Engine` manages many individual DBAPI connections on behalf of the @@ -89,7 +89,7 @@ If the :class:`.ResultProxy` potentially has rows remaining, it can be instructed to close out its resources explicitly:: result.close() - + If the :class:`.ResultProxy` has pending rows remaining and is dereferenced by the application without being closed, Python garbage collection will ultimately close out the cursor as well as trigger a return of the pooled @@ -116,7 +116,7 @@ in :ref:`sqlexpression_toplevel`. .. autoclass:: sqlalchemy.engine.base.ResultProxy :members: - + .. autoclass:: sqlalchemy.engine.base.RowProxy :members: @@ -243,7 +243,7 @@ to use the :meth:`~.Executable.execute` method of any :class:`.Executable` construct, which is a marker for SQL expression objects that support execution. The SQL expression object itself references an :class:`.Engine` or :class:`.Connection` known as the **bind**, which it uses -in order to provide so-called "implicit" execution services. +in order to provide so-called "implicit" execution services. Given a table as below:: diff --git a/doc/build/core/engines.rst b/doc/build/core/engines.rst index dbc7dcc45..0b5ce345d 100644 --- a/doc/build/core/engines.rst +++ b/doc/build/core/engines.rst @@ -46,9 +46,9 @@ SQLAlchemy dialect always requires that an appropriate DBAPI driver is installed The table below summarizes the state of DBAPI support in SQLAlchemy 0.7. The values translate as: -* yes / Python platform - The SQLAlchemy dialect is mostly or fully operational on the target platform. +* yes / Python platform - The SQLAlchemy dialect is mostly or fully operational on the target platform. * yes / OS platform - The DBAPI supports that platform. -* no / Python platform - The DBAPI does not support that platform, or there is no SQLAlchemy dialect support. +* no / Python platform - The DBAPI does not support that platform, or there is no SQLAlchemy dialect support. * no / OS platform - The DBAPI does not support that platform. * partial - the DBAPI is partially usable on the target platform but has major unresolved issues. * development - a development version of the dialect exists, but is not yet usable. @@ -280,7 +280,7 @@ namespace of SA loggers that can be turned on is as follows: * ``sqlalchemy.engine`` - controls SQL echoing. set to ``logging.INFO`` for SQL query output, ``logging.DEBUG`` for query + result set output. * ``sqlalchemy.dialects`` - controls custom logging for SQL dialects. See the documentation of individual dialects for details. * ``sqlalchemy.pool`` - controls connection pool logging. set to ``logging.INFO`` or lower to log connection pool checkouts/checkins. -* ``sqlalchemy.orm`` - controls logging of various ORM functions. set to ``logging.INFO`` for information on mapper configurations. +* ``sqlalchemy.orm`` - controls logging of various ORM functions. set to ``logging.INFO`` for information on mapper configurations. For example, to log SQL queries using Python logging instead of the ``echo=True`` flag:: diff --git a/doc/build/core/event.rst b/doc/build/core/event.rst index f1a428d8c..86cc7d968 100644 --- a/doc/build/core/event.rst +++ b/doc/build/core/event.rst @@ -24,10 +24,10 @@ and that a user-defined listener function should receive two positional argument from sqlalchemy.event import listen from sqlalchemy.pool import Pool - + def my_on_connect(dbapi_con, connection_record): print "New DBAPI connection:", dbapi_con - + listen(Pool, 'connect', my_on_connect) Targets @@ -43,13 +43,13 @@ classes and objects:: from sqlalchemy import create_engine from sqlalchemy.engine import Engine import psycopg2 - + def connect(): return psycopg2.connect(username='ed', host='127.0.0.1', dbname='test') my_pool = QueuePool(connect) my_engine = create_engine('postgresql://ed@localhost/test') - + # associate listener with all instances of Pool listen(Pool, 'connect', my_on_connect) @@ -73,9 +73,9 @@ which modifies the subsequent handling. By default, no listener ever requires def validate_phone(target, value, oldvalue, initiator): """Strip non-numeric characters from a phone number""" - + return re.sub(r'(?![0-9])', '', value) - + # setup listener on UserContact.phone attribute, instructing # it to use the return value listen(UserContact.phone, 'set', validate_phone, retval=True) @@ -89,7 +89,7 @@ Both SQLAlchemy Core and SQLAlchemy ORM feature a wide variety of event hooks: :ref:`core_event_toplevel` and include event hooks specific to connection pool lifecycle, SQL statement execution, transaction lifecycle, and schema creation and teardown. - + * **ORM Events** - these are described in :ref:`orm_event_toplevel`, and include event hooks specific to class and attribute instrumentation, object initialization diff --git a/doc/build/core/expression_api.rst b/doc/build/core/expression_api.rst index 1b4a35f84..e907b2535 100644 --- a/doc/build/core/expression_api.rst +++ b/doc/build/core/expression_api.rst @@ -46,11 +46,11 @@ The expression package uses functions to construct SQL expressions. The return .. autofunction:: extract .. attribute:: func - + Generate SQL function expressions. - + ``func`` is a special object instance which generates SQL functions based on name-based attributes, e.g.:: - + >>> print func.count(1) count(:param_1) @@ -58,29 +58,29 @@ The expression package uses functions to construct SQL expressions. The return SQLAlchemy, it will be rendered exactly as is. For common SQL functions which SQLAlchemy is aware of, the name may be interpreted as a *generic function* which will be compiled appropriately to the target database:: - + >>> print func.current_timestamp() CURRENT_TIMESTAMP - + To call functions which are present in dot-separated packages, specify them in the same manner:: - + >>> print func.stats.yield_curve(5, 10) stats.yield_curve(:yield_curve_1, :yield_curve_2) - + SQLAlchemy can be made aware of the return type of functions to enable type-specific lexical and result-based behavior. For example, to ensure that a string-based function returns a Unicode value and is similarly treated as a string in expressions, specify :class:`~sqlalchemy.types.Unicode` as the type: - + >>> print func.my_string(u'hi', type_=Unicode) + ' ' + \ ... func.my_string(u'there', type_=Unicode) my_string(:my_string_1) || :my_string_2 || my_string(:my_string_3) - + Functions which are interpreted as "generic" functions know how to calculate their return type automatically. For a listing of known generic functions, see :ref:`generic_functions`. - + .. autofunction:: insert .. autofunction:: intersect @@ -179,7 +179,7 @@ Classes .. autoclass:: Function :members: :show-inheritance: - + .. autoclass:: FromClause :members: :show-inheritance: @@ -220,18 +220,18 @@ Generic Functions SQL functions which are known to SQLAlchemy with regards to database-specific rendering, return types and argument behavior. Generic functions are invoked like all SQL functions, using the :attr:`func` attribute:: - + select([func.count()]).select_from(sometable) - + Note that any name not known to :attr:`func` generates the function name as is - there is no restriction on what SQL functions can be called, known or unknown to SQLAlchemy, built-in or user defined. The section here only describes those functions where SQLAlchemy already knows what argument and return types are in use. - + .. automodule:: sqlalchemy.sql.functions :members: :undoc-members: :show-inheritance: - - + + diff --git a/doc/build/core/index.rst b/doc/build/core/index.rst index 6af349322..780016bae 100644 --- a/doc/build/core/index.rst +++ b/doc/build/core/index.rst @@ -5,7 +5,7 @@ SQLAlchemy Core .. toctree:: :maxdepth: 2 - + tutorial expression_api engines @@ -19,5 +19,4 @@ SQLAlchemy Core compiler serializer interfaces - -
\ No newline at end of file + diff --git a/doc/build/core/schema.rst b/doc/build/core/schema.rst index c1f99feeb..3caced3ae 100644 --- a/doc/build/core/schema.rst +++ b/doc/build/core/schema.rst @@ -1217,9 +1217,9 @@ will take over the job of issuing DDL for the constraint. Additionally, the constraint will be added via ALTER: .. sourcecode:: python+sql - + from sqlalchemy import event - + event.listen( users, "after_create", @@ -1251,7 +1251,7 @@ parameter ``dialect``, which is the string name of a dialect or a tuple of such, which will limit the execution of the item to just those dialects. It also accepts a ``callable_`` parameter which may reference a Python callable which will be invoked upon event reception, returning ``True`` or ``False`` indicating if -the event should proceed. +the event should proceed. If our :class:`~sqlalchemy.schema.CheckConstraint` was only supported by Postgresql and not other databases, we could limit its usage to just that dialect:: @@ -1268,7 +1268,7 @@ Postgresql and not other databases, we could limit its usage to just that dialec ) Or to any set of dialects:: - + event.listen( users, "after_create", @@ -1332,7 +1332,7 @@ Custom DDL phrases are most easily achieved using the other DDL elements except it accepts a string which is the text to be emitted: .. sourcecode:: python+sql - + event.listen( metadata, "after_create", diff --git a/doc/build/core/tutorial.rst b/doc/build/core/tutorial.rst index b7d5ba272..543d57ae2 100644 --- a/doc/build/core/tutorial.rst +++ b/doc/build/core/tutorial.rst @@ -1078,7 +1078,7 @@ Finally, we're back to INSERT for some more detail. The :func:`~sqlalchemy.sql.e # insert from a function users.insert().values(id=12, name=func.upper('jack')) - + # insert from a concatenation expression addresses.insert().values(email_address = name + '@' + host) @@ -1088,7 +1088,7 @@ Finally, we're back to INSERT for some more detail. The :func:`~sqlalchemy.sql.e users.insert().values(name=func.upper('jack')), fullname='Jack Jones' ) - + :func:`~sqlalchemy.sql.expression.bindparam` constructs can be passed, however the names of the table's columns are reserved for the "automatic" generation of bind names:: users.insert().values(id=bindparam('_id'), name=bindaparam('_name')) @@ -1102,7 +1102,7 @@ Finally, we're back to INSERT for some more detail. The :func:`~sqlalchemy.sql.e {'_id':3, '_name':'name3'}, ] ) - + Updates work a lot like INSERTS, except there is an additional WHERE clause that can be specified: .. sourcecode:: pycon+sql diff --git a/doc/build/core/types.rst b/doc/build/core/types.rst index 47bbd87d7..d2a56e8e9 100644 --- a/doc/build/core/types.rst +++ b/doc/build/core/types.rst @@ -274,17 +274,17 @@ many decimal places. Here's a recipe that rounds them down:: from sqlalchemy.types import TypeDecorator, Numeric from decimal import Decimal - + class SafeNumeric(TypeDecorator): """Adds quantization to Numeric.""" - + impl = Numeric - + def __init__(self, *arg, **kw): TypeDecorator.__init__(self, *arg, **kw) self.quantize_int = -(self.impl.precision - self.impl.scale) self.quantize = Decimal(10) ** self.quantize_int - + def process_bind_param(self, value, dialect): if isinstance(value, Decimal) and \ value.as_tuple()[2] < self.quantize_int: @@ -305,10 +305,10 @@ binary in CHAR(16) if desired:: class GUID(TypeDecorator): """Platform-independent GUID type. - + Uses Postgresql's UUID type, otherwise uses CHAR(32), storing as stringified hex values. - + """ impl = CHAR @@ -348,11 +348,11 @@ to/from JSON. Can be modified to use Python's builtin json encoder:: class JSONEncodedDict(TypeDecorator): """Represents an immutable structure as a json-encoded string. - + Usage:: - + JSONEncodedDict(255) - + """ impl = VARCHAR @@ -377,7 +377,7 @@ changes, and combine this using the ``sqlalchemy.ext.mutable`` extension described in :ref:`mutable_toplevel`:: from sqlalchemy.ext.mutable import Mutable - + class MutationDict(Mutable, dict): @classmethod def coerce(cls, key, value): @@ -385,15 +385,15 @@ described in :ref:`mutable_toplevel`:: if not isinstance(value, MutationDict): if isinstance(value, dict): return MutationDict(value) - + # this call will raise ValueError return Mutable.coerce(key, value) else: return value - + def __setitem__(self, key, value): """Detect dictionary set events and emit change events.""" - + dict.__setitem__(self, key, value) self.change() @@ -402,7 +402,7 @@ described in :ref:`mutable_toplevel`:: dict.__delitem__(self, key) self.change() - + # additional dict methods would be overridden here The new dictionary type can be associated with JSONEncodedDict using diff --git a/doc/build/index.rst b/doc/build/index.rst index 2d75a5c08..e6442efd0 100644 --- a/doc/build/index.rst +++ b/doc/build/index.rst @@ -3,12 +3,12 @@ Table of Contents .. toctree:: :maxdepth: 2 - + intro orm/index core/index dialects/index - + Indices and tables ------------------ diff --git a/doc/build/intro.rst b/doc/build/intro.rst index b679dca3e..d3409cec3 100644 --- a/doc/build/intro.rst +++ b/doc/build/intro.rst @@ -28,7 +28,7 @@ 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 @@ -71,7 +71,7 @@ this from the command-line: .. sourcecode:: none # easy_install SQLAlchemy - + Or with pip: .. sourcecode:: none diff --git a/doc/build/orm/collections.rst b/doc/build/orm/collections.rst index 7f585fc50..98de8e205 100644 --- a/doc/build/orm/collections.rst +++ b/doc/build/orm/collections.rst @@ -5,7 +5,7 @@ Collection Configuration and Techniques ======================================= -The :func:`.relationship` function defines a linkage between two classes. +The :func:`.relationship` function defines a linkage between two classes. When the linkage defines a one-to-many or many-to-many relationship, it's represented as a Python collection when objects are loaded and manipulated. This section presents additional information about collection configuration @@ -335,21 +335,21 @@ on :class:`.MappedCollection` are already instrumented - calling them from within an already instrumented call can cause events to be fired off repeatedly, or inappropriately, leading to internal state corruption in rare cases:: - + from sqlalchemy.orm.collections import MappedCollection,\ collection class MyMappedCollection(MappedCollection): """Use @internally_instrumented when your methods call down to already-instrumented methods. - + """ - + @collection.internally_instrumented def __setitem__(self, key, value, _sa_initiator=None): # do something with key, value super(MyMappedCollection, self).__setitem__(key, value, _sa_initiator) - + @collection.internally_instrumented def __delitem__(self, key, _sa_initiator=None): # do something with key diff --git a/doc/build/orm/extensions/associationproxy.rst b/doc/build/orm/extensions/associationproxy.rst index 4a7ce5dbf..c0b99cc5c 100644 --- a/doc/build/orm/extensions/associationproxy.rst +++ b/doc/build/orm/extensions/associationproxy.rst @@ -287,7 +287,7 @@ of the ``Holding`` while also giving access to ``.shares``:: session.add(broker) session.commit() - + # lets take a peek at that holdings_table after committing changes to the db print list(holdings_table.select().execute()) # [(1, 'ZZK', 10), (1, 'JEK', 123), (1, 'STEPZ', 123)] diff --git a/doc/build/orm/extensions/horizontal_shard.rst b/doc/build/orm/extensions/horizontal_shard.rst index 67cd707d8..deb97a74c 100644 --- a/doc/build/orm/extensions/horizontal_shard.rst +++ b/doc/build/orm/extensions/horizontal_shard.rst @@ -8,7 +8,7 @@ API Documentation .. autoclass:: ShardedSession :members: - + .. autoclass:: ShardedQuery :members: diff --git a/doc/build/orm/extensions/mutable.rst b/doc/build/orm/extensions/mutable.rst index 9844f9b09..0b15e7a60 100644 --- a/doc/build/orm/extensions/mutable.rst +++ b/doc/build/orm/extensions/mutable.rst @@ -10,7 +10,7 @@ API Reference .. autoclass:: Mutable :members: - + .. autoclass:: MutableComposite :members: diff --git a/doc/build/orm/index.rst b/doc/build/orm/index.rst index af6b0c365..b17fe7547 100644 --- a/doc/build/orm/index.rst +++ b/doc/build/orm/index.rst @@ -5,7 +5,7 @@ SQLAlchemy ORM .. toctree:: :maxdepth: 2 - + tutorial mapper_config relationships @@ -19,5 +19,4 @@ SQLAlchemy ORM extensions/index examples interfaces - -
\ No newline at end of file + diff --git a/doc/build/orm/inheritance.rst b/doc/build/orm/inheritance.rst index 65bcd06f9..ff932f0f3 100644 --- a/doc/build/orm/inheritance.rst +++ b/doc/build/orm/inheritance.rst @@ -261,7 +261,7 @@ what's specified in the :meth:`.Session.query`, :meth:`.Query.filter`, or :meth:`.Query.select_from` methods:: session.query(Manager.manager_data).select_from(manager) - + session.query(engineer.c.id).filter(engineer.c.engineer_info==manager.c.manager_data) Creating Joins to Specific Subtypes @@ -530,17 +530,17 @@ to the parent: with_polymorphic=('*', pjoin), polymorphic_on=pjoin.c.type, polymorphic_identity='employee') - + mapper(Manager, managers_table, inherits=employee_mapper, concrete=True, polymorphic_identity='manager') - + mapper(Engineer, engineers_table, inherits=employee_mapper, concrete=True, polymorphic_identity='engineer') - + mapper(Company, companies, properties={ 'employees': relationship(Employee) }) diff --git a/doc/build/orm/loading.rst b/doc/build/orm/loading.rst index afe4ff6b6..e2fc9f6dd 100644 --- a/doc/build/orm/loading.rst +++ b/doc/build/orm/loading.rst @@ -7,7 +7,7 @@ Relationship Loading Techniques A big part of SQLAlchemy is providing a wide range of control over how related objects get loaded when querying. This behavior can be configured at mapper construction time using the ``lazy`` parameter to the :func:`.relationship` function, -as well as by using options with the :class:`.Query` object. +as well as by using options with the :class:`.Query` object. Using Loader Strategies: Lazy Loading, Eager Loading ---------------------------------------------------- @@ -59,7 +59,7 @@ additional SQL statement for each collection requested, aggregated across all parent objects: .. sourcecode:: python+sql - + {sql}>>>jack = session.query(User).options(subqueryload('addresses')).filter_by(name='jack').all() SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password @@ -187,7 +187,7 @@ references a scalar many-to-one reference. * When using the default lazy loading, if you load 100 objects, and then access a collection on each of them, a total of 101 SQL statements will be emitted, although each statement will typically be a simple SELECT without any joins. - + * When using joined loading, the load of 100 objects and their collections will emit only one SQL statement. However, the total number of rows fetched will be equal to the sum of the size of all the collections, plus one @@ -197,16 +197,16 @@ references a scalar many-to-one reference. exceptions) will transmit the full data of each parent over the wire to the client connection in any case. Therefore joined eager loading only makes sense when the size of the collections are relatively small. The LEFT OUTER JOIN can also be performance intensive compared to an INNER join. - + * When using subquery loading, the load of 100 objects will emit two SQL statements. The second statement will fetch a total number of rows equal to the sum of the size of all collections. An INNER JOIN is used, and a minimum of parent columns are requested, only the primary keys. So a subquery load makes sense when the collections are larger. - + * When multiple levels of depth are used with joined or subquery loading, loading collections-within- collections will multiply the total number of rows fetched in a cartesian fashion. Both forms of eager loading always join from the original parent class. - + * Many to One Reference * When using the default lazy loading, a load of 100 objects will like in the case of the collection @@ -216,15 +216,15 @@ references a scalar many-to-one reference. if the collection of objects references a relatively small set of target objects, or the full set of possible target objects have already been loaded into the session and are strongly referenced, using the default of `lazy='select'` is by far the most efficient way to go. - + * When using joined loading, the load of 100 objects will emit only one SQL statement. The join - will be a LEFT OUTER JOIN, and the total number of rows will be equal to 100 in all cases. + will be a LEFT OUTER JOIN, and the total number of rows will be equal to 100 in all cases. If you know that each parent definitely has a child (i.e. the foreign key reference is NOT NULL), the joined load can be configured with ``innerjoin=True``, which is usually specified within the :func:`~sqlalchemy.orm.relationship`. For a load of objects where there are many possible target references which may have not been loaded already, joined loading with an INNER JOIN is extremely efficient. - + * Subquery loading will issue a second load for all the child objects, so for a load of 100 objects there would be two SQL statements emitted. There's probably not much advantage here over joined loading, however, except perhaps that subquery loading can use an INNER JOIN in all cases diff --git a/doc/build/orm/mapper_config.rst b/doc/build/orm/mapper_config.rst index 4c57b8c45..7c0641147 100644 --- a/doc/build/orm/mapper_config.rst +++ b/doc/build/orm/mapper_config.rst @@ -15,7 +15,7 @@ Note that all patterns here apply both to the usage of explicit takes a form such as:: mapper(User, users_table, primary_key=[users_table.c.id]) - + Would translate into declarative as:: class User(Base): @@ -29,9 +29,9 @@ with the class definition. These are usable as is within ``__mapper_args__``:: class User(Base): __tablename__ = 'users' - + id = Column(Integer) - + __mapper_args__ = { 'primary_key':[id] } @@ -52,7 +52,7 @@ use the ``include_properties`` or ``exclude_properties`` arguments. For example:: mapper(User, users_table, include_properties=['user_id', 'user_name']) - + ...will map the ``User`` class to the ``users_table`` table, only including the "user_id" and "user_name" columns - the rest are not refererenced. Similarly:: @@ -106,7 +106,7 @@ using the desired attribute name in the class definition:: from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() - + class User(Base): __tablename__ = 'user' id = Column('user_id', Integer, primary_key=True) @@ -130,7 +130,7 @@ key relationship or join condition into the same mapped attribute, put them together using a list, as below where we map to a :func:`~.expression.join`:: from sqlalchemy.sql import join - + # join users and addresses usersaddresses = join(users_table, addresses_table, \ users_table.c.user_id == addresses_table.c.user_id) @@ -152,21 +152,21 @@ usually invoked implicitly for each mapped :class:`.Column`. Explicit usage looks like:: from sqlalchemy.orm import mapper, column_property - + mapper(User, users, properties={ 'name':column_property(users.c.name, active_history=True) }) or with declarative:: - + class User(Base): __tablename__ = 'users' - + id = Column(Integer, primary_key=True) name = column_property(Column(String(50)), active_history=True) Further examples of :func:`.column_property` are at :ref:`mapper_sql_expressions`. - + .. autofunction:: column_property .. _deferred: @@ -204,7 +204,7 @@ With declarative, :class:`.Column` objects can be declared directly inside of :f class Book(Base): __tablename__ = 'books' - + book_id = Column(Integer, primary_key=True) title = Column(String(200), nullable=False) summary = Column(String(2000)) @@ -273,7 +273,7 @@ scalar-returning used. Unlike older versions of SQLAlchemy, there is no :func:`~.sql.expression.label` requirement:: from sqlalchemy.orm import column_property - + mapper(User, users_table, properties={ 'fullname': column_property( users_table.c.firstname + " " + users_table.c.lastname @@ -284,7 +284,7 @@ Correlated subqueries may be used as well:: from sqlalchemy.orm import column_property from sqlalchemy import select, func - + mapper(User, users_table, properties={ 'address_count': column_property( select([func.count(addresses_table.c.address_id)]).\ @@ -305,7 +305,7 @@ loaded:: @property def fullname(self): return self.firstname + " " + self.lastname - + To invoke a SQL statement from an instance that's already been loaded, the session associated with the instance can be acquired using :func:`~.session.object_session` which will provide the appropriate @@ -313,7 +313,7 @@ transactional context from which to emit a statement:: from sqlalchemy.orm import object_session from sqlalchemy import select, func - + class User(object): @property def address_count(self): @@ -343,9 +343,9 @@ attribute extensions, are only called by normal userland code; they are not issued when the ORM is populating the object. .. sourcecode:: python+sql - + from sqlalchemy.orm import validates - + addresses_table = Table('addresses', metadata, Column('id', Integer, primary_key=True), Column('email', String) @@ -383,11 +383,11 @@ plain descriptor, and to have it read/write from a mapped attribute with a different name. Below we illustrate this using Python 2.6-style properties:: class EmailAddress(object): - + @property def email(self): return self._email - + @email.setter def email(self, email): self._email = email @@ -456,7 +456,7 @@ do case-insensitive comparison:: from sqlalchemy.orm.properties import ColumnProperty from sqlalchemy.sql import func - + class MyComparator(ColumnProperty.Comparator): def __eq__(self, other): return func.lower(self.__clause_element__()) == func.lower(other) @@ -496,13 +496,13 @@ class you provide. As of SQLAlchemy 0.7, composites are implemented as a simple wrapper using the :ref:`hybrids_toplevel` feature. Note that composites no longer "conceal" the underlying colunm based attributes, or support in-place - mutation. + mutation. -A simple example represents pairs of columns as a "Point" object. +A simple example represents pairs of columns as a "Point" object. Starting with a table that represents two points as x1/y1 and x2/y2:: from sqlalchemy import Table, Column - + vertices = Table('vertices', metadata, Column('id', Integer, primary_key=True), Column('x1', Integer), @@ -597,7 +597,7 @@ passed in to a mapper as the table. from sqlalchemy.orm import mapper from sqlalchemy.sql import join - + class AddressUser(object): pass @@ -614,7 +614,7 @@ Note that the list of columns is equivalent to the usage of :func:`.column_prope with multiple columns:: from sqlalchemy.orm import mapper, column_property - + mapper(AddressUser, j, properties={ 'user_id': column_property(users_table.c.user_id, addresses_table.c.user_id) }) @@ -624,12 +624,12 @@ to multiple columns, since the declarative class parser won't recognize a plain list of columns:: from sqlalchemy.ext.declarative import declarative_base - + Base = declarative_base() - + class AddressUser(Base): __table__ = j - + user_id = column_property(users_table.c.user_id, addresses_table.c.user_id) A second example:: diff --git a/doc/build/orm/relationships.rst b/doc/build/orm/relationships.rst index f9337a5f6..a4ac63ee7 100644 --- a/doc/build/orm/relationships.rst +++ b/doc/build/orm/relationships.rst @@ -63,20 +63,20 @@ To establish a bi-directional relationship in one-to-many, where the "reverse" s ``Child`` will get a ``parent`` attribute with many-to-one semantics. Declarative:: - + from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() - + class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship("Child", backref="parent") - + class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey('parent.id')) - + Many To One ~~~~~~~~~~~~ @@ -125,7 +125,7 @@ Declarative:: id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", backref="parents") - + class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) @@ -150,14 +150,14 @@ of the relationship. To convert one-to-many into one-to-one:: mapper(Parent, parent_table, properties={ 'child': relationship(Child, uselist=False, backref='parent') }) - + mapper(Child, child_table) Or to turn a one-to-many backref into one-to-one, use the :func:`.backref` function to provide arguments for the reverse side:: - + from sqlalchemy.orm import backref - + parent_table = Table('parent', metadata, Column('id', Integer, primary_key=True), Column('child_id', Integer, ForeignKey('child.id')) @@ -183,11 +183,11 @@ The second example above as declarative:: id = Column(Integer, primary_key=True) child_id = Column(Integer, ForeignKey('child.id')) child = relationship("Child", backref=backref("parent", uselist=False)) - + class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) - + Many To Many ~~~~~~~~~~~~~ @@ -238,18 +238,18 @@ plain schematic form:: Column('left_id', Integer, ForeignKey('left.id')), Column('right_id', Integer, ForeignKey('right.id')) ) - + class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship("Child", secondary=association_table, backref="parents") - + class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True) - + .. _association_pattern: Association Object @@ -313,16 +313,16 @@ Declarative:: left_id = Column(Integer, ForeignKey('left.id'), primary_key=True) right_id = Column(Integer, ForeignKey('right.id'), primary_key=True) child = relationship("Child", backref="parent_assocs") - + class Parent(Base): __tablename__ = 'left' id = Column(Integer, primary_key=True) children = relationship(Association, backref="parent") - + class Child(Base): __tablename__ = 'right' id = Column(Integer, primary_key=True) - + Working with the association pattern in its direct form requires that child objects are associated with an association instance before being appended to the parent; similarly, access from parent to child goes through the @@ -442,7 +442,7 @@ when the collection is only one column):: from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() - + class Node(Base): __tablename__ = 'nodes' id = Column(Integer, primary_key=True) @@ -451,7 +451,7 @@ when the collection is only one column):: children = relationship("Node", backref=backref('parent', remote_side=id) ) - + There are several examples included with SQLAlchemy illustrating self-referential strategies; these include :ref:`examples_adjacencylist` and :ref:`examples_xmlpersistence`. @@ -761,7 +761,7 @@ A typical mutable primary key setup might look like: # passive_updates=False *only* needed if the database # does not implement ON UPDATE CASCADE - + mapper(User, users, properties={ 'addresses': relationship(Address, passive_updates=False) }) diff --git a/doc/build/orm/session.rst b/doc/build/orm/session.rst index d08ce5f5a..7e0c8bb83 100644 --- a/doc/build/orm/session.rst +++ b/doc/build/orm/session.rst @@ -91,10 +91,10 @@ to acquire connection resources. This association can be set up as in the example above, using the ``bind`` argument. You can also associate a :class:`.Engine` with an existing :func:`.sessionmaker` using the :meth:`.sessionmaker.configure` method:: - + from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine - + # configure Session class with desired options Session = sessionmaker() @@ -111,7 +111,7 @@ you can also associate individual :class:`.Session` objects with an :class:`.Eng on each invocation:: session = Session(bind=engine) - + ...or directly with a :class:`.Connection`:: conn = engine.connect() @@ -167,12 +167,12 @@ Frequently Asked Questions that point on your other modules say "from mypackage import Session". That way, everyone else just uses :class:`.Session()`, and the configuration of that session is controlled by that central point. - + If your application starts up, does imports, but does not know what database it's going to be connecting to, you can bind the :class:`.Session` at the "class" level to the engine later on, using ``configure()``. - + In the examples in this section, we will frequently show the :func:`.sessionmaker` being created right above the line where we actually invoke :class:`~sqlalchemy.orm.session.Session()`. But that's just for @@ -189,7 +189,7 @@ Frequently Asked Questions then remains in use for the lifespan of a particular database conversation, which includes not just the initial loading of objects but throughout the whole usage of those instances. - + Objects become detached if their owning session is discarded. They are still functional in the detached state if the user has ensured that their state has not been expired before detachment, but they will not be able to @@ -197,14 +197,14 @@ Frequently Asked Questions to consider persisted objects as an extension of the state of a particular :class:`.Session`, and to keep that session around until all referenced objects have been discarded. - + An exception to this is when objects are placed in caches or otherwise shared among threads or processes, in which case their detached state can be stored, transmitted, or shared. However, the state of detached objects should still be transferred back into a new :class:`.Session` using :meth:`.Session.add` or :meth:`.Session.merge` before working with the object (or in the case of merge, its state) again. - + It is also very common that a :class:`.Session` as well as its associated objects are only referenced by a single thread. Sharing objects between threads is most safely accomplished by sharing their state among multiple @@ -212,7 +212,7 @@ Frequently Asked Questions :class:`.Session` per thread, :meth:`.Session.merge` to transfer state between threads. This pattern is not a strict requirement by any means, but it has the least chance of introducing concurrency issues. - + To help with the recommended :class:`.Session` -per-thread, :class:`.Session` -per-set-of-objects patterns, the :func:`.scoped_session` function is provided which produces a @@ -233,10 +233,10 @@ Frequently Asked Questions map and see that the object is already there. It's only when you say ``query.get({some primary key})`` that the :class:`~sqlalchemy.orm.session.Session` doesn't have to issue a query. - + Additionally, the Session stores object instances using a weak reference by default. This also defeats the purpose of using the Session as a cache. - + The :class:`.Session` is not designed to be a global object from which everyone consults as a "registry" of objects. That's more the job of a **second level cache**. SQLAlchemy provides @@ -278,7 +278,7 @@ Frequently Asked Questions sharing the session with those threads, but you also will have implemented a proper locking scheme (or your graphical framework does) so that those threads do not collide. - + A multithreaded application is usually going to want to make usage of :func:`.scoped_session` to transparently manage sessions per thread. More on this at :ref:`unitofwork_contextual`. @@ -416,33 +416,33 @@ Merge Tips :meth:`~.Session.merge` is an extremely useful method for many purposes. However, it deals with the intricate border between objects that are transient/detached and -those that are persistent, as well as the automated transferrence of state. +those that are persistent, as well as the automated transferrence of state. The wide variety of scenarios that can present themselves here often require a more careful approach to the state of objects. Common problems with merge usually involve -some unexpected state regarding the object being passed to :meth:`~.Session.merge`. +some unexpected state regarding the object being passed to :meth:`~.Session.merge`. Lets use the canonical example of the User and Address objects:: class User(Base): __tablename__ = 'user' - + id = Column(Integer, primary_key=True) name = Column(String(50), nullable=False) addresses = relationship("Address", backref="user") - + class Address(Base): __tablename__ = 'address' id = Column(Integer, primary_key=True) email_address = Column(String(50), nullable=False) user_id = Column(Integer, ForeignKey('user.id'), nullable=False) - + Assume a ``User`` object with one ``Address``, already persistent:: >>> u1 = User(name='ed', addresses=[Address(email_address='ed@ed.com')]) >>> session.add(u1) >>> session.commit() - + We now create ``a1``, an object outside the session, which we'd like to merge on top of the existing ``Address``:: @@ -450,7 +450,7 @@ to merge on top of the existing ``Address``:: >>> a1 = Address(id=existing_a1.id) A surprise would occur if we said this:: - + >>> a1.user = u1 >>> a1 = session.merge(a1) >>> session.commit() @@ -508,7 +508,7 @@ is equivalent to:: >>> existing_a1.id = existing_a1.id >>> existing_a1.user_id = u1.id >>> existing_a1.user = None - + Where above, both ``user_id`` and ``user`` are assigned to, and change events are emitted for both. The ``user`` association takes precedence, and None is applied to ``user_id``, causing a failure. @@ -517,11 +517,11 @@ Most :meth:`~.Session.merge` issues can be examined by first checking - is the object prematurely in the session ? .. sourcecode:: python+sql - + >>> a1 = Address(id=existing_a1, user_id=user.id) >>> assert a1 not in session >>> a1 = session.merge(a1) - + Or is there state on the object that we don't want ? Examining ``__dict__`` is a quick way to check:: @@ -537,7 +537,7 @@ is a quick way to check:: >>> a1 = session.merge(a1) >>> # success >>> session.commit() - + Deleting -------- @@ -900,14 +900,14 @@ place:: >>> session.add(o1) >>> o1 in session True - + >>> i1 = Item() >>> i1.order = o1 >>> i1 in o1.orders True >>> i1 in session True - + This behavior can be disabled as of 0.6.5 using the ``cascade_backrefs`` flag:: mapper(Order, order_table, properties={ @@ -1241,7 +1241,7 @@ entire database interaction is rolled back:: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from unittest import TestCase - + # global application scope. create Session class, engine Session = sessionmaker() @@ -1254,23 +1254,23 @@ entire database interaction is rolled back:: # begin a non-ORM transaction self.trans = connection.begin() - + # bind an individual Session to the connection self.session = Session(bind=self.connection) - + def test_something(self): - # use the session in tests. - + # use the session in tests. + self.session.add(Foo()) self.session.commit() - + def tearDown(self): # rollback - everything that happened with the # Session above (including calls to commit()) # is rolled back. self.trans.rollback() self.session.close() - + Above, we issue :meth:`.Session.commit` as well as :meth:`.Transaction.rollback`. This is an example of where we take advantage of the :class:`.Connection` object's ability to maintain *subtransactions*, or @@ -1414,7 +1414,7 @@ Contextual Session API .. autoclass:: sqlalchemy.util.ScopedRegistry :members: - + .. autoclass:: sqlalchemy.util.ThreadLocalRegistry .. _session_partitioning: @@ -1490,7 +1490,7 @@ those described in :ref:`events_orm_toplevel`. .. autoclass:: History :members: - + .. attribute:: sqlalchemy.orm.attributes.PASSIVE_NO_INITIALIZE Symbol indicating that loader callables should diff --git a/doc/build/orm/tutorial.rst b/doc/build/orm/tutorial.rst index b0a4b24c2..2dedf7049 100644 --- a/doc/build/orm/tutorial.rst +++ b/doc/build/orm/tutorial.rst @@ -185,10 +185,10 @@ Creating Table, Class and Mapper All at Once Declaratively The preceding approach to configuration involved a :class:`~sqlalchemy.schema.Table`, a user-defined class, and a call to :func:`~.orm.mapper`. This illustrates classical SQLAlchemy usage, which values -the highest separation of concerns possible. +the highest separation of concerns possible. A large number of applications don't require this degree of separation, and for those SQLAlchemy offers an alternate "shorthand" -configurational style called :mod:`~.sqlalchemy.ext.declarative`. +configurational style called :mod:`~.sqlalchemy.ext.declarative`. For many applications, this is the only style of configuration needed. Our above example using this style is as follows:: @@ -1440,7 +1440,7 @@ completely and start again. >>> session.close() # roll back and close the transaction >>> from sqlalchemy.orm import clear_mappers >>> clear_mappers() # remove all class mappings - + Below, we use :class:`~.orm.mapper` to reconfigure an ORM mapping for ``User`` and ``Address``, on our existing but currently un-mapped classes. The diff --git a/doc/build/static/docs.css b/doc/build/static/docs.css index 23513dbba..697837e94 100644 --- a/doc/build/static/docs.css +++ b/doc/build/static/docs.css @@ -86,7 +86,7 @@ h1 { font: normal 20px/22px arial,helvetica,sans-serif; color: #222; padding:0px; - margin:0px; + margin:0px; } .topnav h2 { @@ -94,7 +94,7 @@ h1 { font-family:arial,helvetica,sans-serif; font-size:1.6em; font-weight:normal; - line-height:1.6em; + line-height:1.6em; } .topnav h3 { @@ -185,7 +185,7 @@ div.admonition .admonition-title { } .totoc { - + } .doc_copyright { diff --git a/doc/build/templates/genindex.mako b/doc/build/templates/genindex.mako index bdb699a66..b8f776dd2 100644 --- a/doc/build/templates/genindex.mako +++ b/doc/build/templates/genindex.mako @@ -30,7 +30,7 @@ % else: ${entryname|h} % endif - + % if subitems: <dd><dl> % for subentryname, subentrylinks in subitems: diff --git a/doc/build/templates/layout.mako b/doc/build/templates/layout.mako index d842fdd63..879818efa 100644 --- a/doc/build/templates/layout.mako +++ b/doc/build/templates/layout.mako @@ -58,12 +58,12 @@ <div class="topnav"> <div id="pagecontrol"> <a href="${pathto('genindex')}">Index</a> - + % if sourcename: <div class="sourcelink">(<a href="${pathto('_sources/' + sourcename, True)|h}">${_('view source')})</div> % endif </div> - + <div class="navbanner"> <a class="totoc" href="${pathto(master_doc)}">Table of Contents</a> % if parents: @@ -74,7 +74,7 @@ % if current_page_name != master_doc: ยป ${self.show_title()} % endif - + ${prevnext()} <h2> ${self.show_title()} @@ -85,7 +85,7 @@ % endif <div class="clearboth"></div> </div> - + <div class="document"> <div class="body"> ${next.body()} |
