Commits

Mike Bayer committed 5370eb7

pep8

  • Participants
  • Parent commits b6a8705

Comments (0)

Files changed (1)

File lib/sqlalchemy/ext/hybrid.py

 "hybrid" means the attribute has distinct behaviors defined at the
 class level and at the instance level.
 
-The :mod:`~sqlalchemy.ext.hybrid` extension provides a special form of method
-decorator, is around 50 lines of code and has almost no dependencies on the rest
-of SQLAlchemy.  It can, in theory, work with any descriptor-based expression
-system.
+The :mod:`~sqlalchemy.ext.hybrid` extension provides a special form of
+method decorator, is around 50 lines of code and has almost no
+dependencies on the rest of SQLAlchemy.  It can, in theory, work with
+any descriptor-based expression system.
 
 Consider a mapping ``Interval``, representing integer ``start`` and ``end``
 values. We can define higher level functions on mapped classes that produce
         def intersects(self, other):
             return self.contains(other.start) | self.contains(other.end)
 
-Above, the ``length`` property returns the difference between the ``end`` and
-``start`` attributes.  With an instance of ``Interval``, this subtraction occurs
-in Python, using normal Python descriptor mechanics::
+Above, the ``length`` property returns the difference between the
+``end`` and ``start`` attributes.  With an instance of ``Interval``,
+this subtraction occurs in Python, using normal Python descriptor
+mechanics::
 
     >>> i1 = Interval(5, 10)
     >>> i1.length
     FROM interval
     WHERE interval."end" - interval.start = :param_1
 
-The ``Interval`` class example also illustrates two methods, ``contains()`` and ``intersects()``,
-decorated with :class:`.hybrid_method`.
-This decorator applies the same idea to methods that :class:`.hybrid_property` applies
-to attributes.   The methods return boolean values, and take advantage
-of the Python ``|`` and ``&`` bitwise operators to produce equivalent instance-level and
+The ``Interval`` class example also illustrates two methods,
+``contains()`` and ``intersects()``, decorated with
+:class:`.hybrid_method`. This decorator applies the same idea to
+methods that :class:`.hybrid_property` applies to attributes.   The
+methods return boolean values, and take advantage of the Python ``|``
+and ``&`` bitwise operators to produce equivalent instance-level and
 SQL expression-level boolean behavior::
 
     >>> i1.contains(6)
 Defining Expression Behavior Distinct from Attribute Behavior
 --------------------------------------------------------------
 
-Our usage of the ``&`` and ``|`` bitwise operators above was fortunate, considering
-our functions operated on two boolean values to return a new one.   In many cases, the construction
-of an in-Python function and a SQLAlchemy SQL expression have enough differences that two
-separate Python expressions should be defined.  The :mod:`~sqlalchemy.ext.hybrid` decorators
-define the :meth:`.hybrid_property.expression` modifier for this purpose.   As an example we'll
-define the radius of the interval, which requires the usage of the absolute value function::
+Our usage of the ``&`` and ``|`` bitwise operators above was
+fortunate, considering our functions operated on two boolean values to
+return a new one.   In many cases, the construction of an in-Python
+function and a SQLAlchemy SQL expression have enough differences that
+two separate Python expressions should be defined.  The
+:mod:`~sqlalchemy.ext.hybrid` decorators define the
+:meth:`.hybrid_property.expression` modifier for this purpose.   As an
+example we'll define the radius of the interval, which requires the
+usage of the absolute value function::
 
     from sqlalchemy import func
 
         def radius(cls):
             return func.abs(cls.length) / 2
 
-Above the Python function ``abs()`` is used for instance-level operations, the SQL function
-``ABS()`` is used via the :attr:`.func` object for class-level expressions::
+Above the Python function ``abs()`` is used for instance-level
+operations, the SQL function ``ABS()`` is used via the :attr:`.func`
+object for class-level expressions::
 
     >>> i1.radius
     2
 Defining Setters
 ----------------
 
-Hybrid properties can also define setter methods.  If we wanted ``length`` above, when
-set, to modify the endpoint value::
+Hybrid properties can also define setter methods.  If we wanted
+``length`` above, when set, to modify the endpoint value::
 
     class Interval(object):
         # ...
 Working with Relationships
 --------------------------
 
-There's no essential difference when creating hybrids that work with related objects as
-opposed to column-based data. The need for distinct expressions tends to be greater.
-Consider the following declarative mapping which relates a ``User`` to a ``SavingsAccount``::
+There's no essential difference when creating hybrids that work with
+related objects as opposed to column-based data. The need for distinct
+expressions tends to be greater. Consider the following declarative
+mapping which relates a ``User`` to a ``SavingsAccount``::
 
     from sqlalchemy import Column, Integer, ForeignKey, Numeric, String
     from sqlalchemy.orm import relationship
         def balance(cls):
             return SavingsAccount.balance
 
-The above hybrid property ``balance`` works with the first ``SavingsAccount`` entry in the list of
-accounts for this user.   The in-Python getter/setter methods can treat ``accounts`` as a Python
+The above hybrid property ``balance`` works with the first
+``SavingsAccount`` entry in the list of accounts for this user.   The
+in-Python getter/setter methods can treat ``accounts`` as a Python
 list available on ``self``.
 
-However, at the expression level, we can't travel along relationships to column attributes
-directly since SQLAlchemy is explicit about joins.   So here, it's expected that the ``User`` class will be
-used in an appropriate context such that an appropriate join to ``SavingsAccount`` will be present::
+However, at the expression level, we can't travel along relationships
+to column attributes directly since SQLAlchemy is explicit about
+joins.   So here, it's expected that the ``User`` class will be used
+in an appropriate context such that an appropriate join to
+``SavingsAccount`` will be present::
 
-    >>> print Session().query(User, User.balance).join(User.accounts).filter(User.balance > 5000)
-    SELECT "user".id AS user_id, "user".name AS user_name, account.balance AS account_balance
+    >>> print Session().query(User, User.balance).\
+    ...     join(User.accounts).filter(User.balance > 5000)
+    SELECT "user".id AS user_id, "user".name AS user_name,
+    account.balance AS account_balance
     FROM "user" JOIN account ON "user".id = account.user_id
     WHERE account.balance > :balance_1
 
-Note however, that while the instance level accessors need to worry about whether ``self.accounts``
-is even present, this issue expresses itself differently at the SQL expression level, where we basically
+Note however, that while the instance level accessors need to worry
+about whether ``self.accounts`` is even present, this issue expresses
+itself differently at the SQL expression level, where we basically
 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)))
-    SELECT "user".id AS user_id, "user".name AS user_name, account.balance AS account_balance
+    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
 
 Building Custom Comparators
 ---------------------------
 
-The hybrid property also includes a helper that allows construction of custom comparators.
-A comparator object allows one to customize the behavior of each SQLAlchemy expression
-operator individually.  They are useful when creating custom types that have
-some highly idiosyncratic behavior on the SQL side.
+The hybrid property also includes a helper that allows construction of
+custom comparators. A comparator object allows one to customize the
+behavior of each SQLAlchemy expression operator individually.  They
+are useful when creating custom types that have some highly
+idiosyncratic behavior on the SQL side.
 
 The example class below allows case-insensitive comparisons on the attribute
 named ``word_insensitive``::
     FROM searchword
     WHERE lower(searchword.word) = lower(:lower_1)
 
-The ``CaseInsensitiveComparator`` above implements part of the :class:`.ColumnOperators`
-interface.   A "coercion" operation like lowercasing can be applied to all comparison operations
-(i.e. ``eq``, ``lt``, ``gt``, etc.) using :meth:`.Operators.operate`::
+The ``CaseInsensitiveComparator`` above implements part of the
+:class:`.ColumnOperators` interface.   A "coercion" operation like
+lowercasing can be applied to all comparison operations (i.e. ``eq``,
+``lt``, ``gt``, etc.) using :meth:`.Operators.operate`::
 
     class CaseInsensitiveComparator(Comparator):
         def operate(self, op, other):
 Hybrid Value Objects
 --------------------
 
-Note in our previous example, if we were to compare the ``word_insensitive`` attribute of
-a ``SearchWord`` instance to a plain Python string, the plain Python string would not
-be coerced to lower case - the ``CaseInsensitiveComparator`` we built, being returned
-by ``@word_insensitive.comparator``, only applies to the SQL side.
+Note in our previous example, if we were to compare the
+``word_insensitive`` attribute of a ``SearchWord`` instance to a plain
+Python string, the plain Python string would not be coerced to lower
+case - the ``CaseInsensitiveComparator`` we built, being returned by
+``@word_insensitive.comparator``, only applies to the SQL side.
 
-A more comprehensive form of the custom comparator is to construct a *Hybrid Value Object*.
-This technique applies the target value or expression to a value object which is then
-returned by the accessor in all cases.   The value object allows control
-of all operations upon the value as well as how compared values are treated, both
-on the SQL expression side as well as the Python value side.   Replacing the
-previous ``CaseInsensitiveComparator`` class with a new ``CaseInsensitiveWord`` class::
+A more comprehensive form of the custom comparator is to construct a
+*Hybrid Value Object*. This technique applies the target value or
+expression to a value object which is then returned by the accessor in
+all cases.   The value object allows control of all operations upon
+the value as well as how compared values are treated, both on the SQL
+expression side as well as the Python value side.   Replacing the
+previous ``CaseInsensitiveComparator`` class with a new
+``CaseInsensitiveWord`` class::
 
     class CaseInsensitiveWord(Comparator):
         "Hybrid value representing a lower case representation of a word."
         key = 'word'
         "Label to apply to Query tuple results"
 
-Above, the ``CaseInsensitiveWord`` object represents ``self.word``, which may be a SQL function,
-or may be a Python native.   By overriding ``operate()`` and ``__clause_element__()``
-to work in terms of ``self.word``, all comparison operations will work against the
+Above, the ``CaseInsensitiveWord`` object represents ``self.word``,
+which may be a SQL function, or may be a Python native.   By
+overriding ``operate()`` and ``__clause_element__()`` to work in terms
+of ``self.word``, all comparison operations will work against the
 "converted" form of ``word``, whether it be SQL side or Python side.
-Our ``SearchWord`` class can now deliver the ``CaseInsensitiveWord`` object unconditionally
-from a single hybrid call::
+Our ``SearchWord`` class can now deliver the ``CaseInsensitiveWord``
+object unconditionally from a single hybrid call::
 
     class SearchWord(Base):
         __tablename__ = 'searchword'
         def word_insensitive(self):
             return CaseInsensitiveWord(self.word)
 
-The ``word_insensitive`` attribute now has case-insensitive comparison behavior
-universally, including SQL expression vs. Python expression (note the Python value is
-converted to lower case on the Python side here)::
+The ``word_insensitive`` attribute now has case-insensitive comparison
+behavior universally, including SQL expression vs. Python expression
+(note the Python value is converted to lower case on the Python side
+here)::
 
     >>> print Session().query(SearchWord).filter_by(word_insensitive="Trucks")
     SELECT searchword.id AS searchword_id, searchword.word AS searchword_word
     ...                        filter(
     ...                            sw1.word_insensitive > sw2.word_insensitive
     ...                        )
-    SELECT lower(searchword_1.word) AS lower_1, lower(searchword_2.word) AS lower_2
+    SELECT lower(searchword_1.word) AS lower_1,
+    lower(searchword_2.word) AS lower_2
     FROM searchword AS searchword_1, searchword AS searchword_2
     WHERE lower(searchword_1.word) > lower(searchword_2.word)
 
     >>> print ws1.word_insensitive
     someword
 
-The Hybrid Value pattern is very useful for any kind of value that may have multiple representations,
-such as timestamps, time deltas, units of measurement, currencies and encrypted passwords.
+The Hybrid Value pattern is very useful for any kind of value that may
+have multiple representations, such as timestamps, time deltas, units
+of measurement, currencies and encrypted passwords.
 
 See Also:
 
 Building Transformers
 ----------------------
 
-A *transformer* is an object which can receive a :class:`.Query` object and return a
-new one.   The :class:`.Query` object includes a method :meth:`.with_transformation`
-that simply returns a new :class:`.Query` transformed by the given function.
+A *transformer* is an object which can receive a :class:`.Query`
+object and return a new one.   The :class:`.Query` object includes a
+method :meth:`.with_transformation` that returns a new :class:`.Query`
+transformed by the given function.
 
 We can combine this with the :class:`.Comparator` class to produce one type
 of recipe which can both set up the FROM clause of a query as well as assign
 filtering criterion.
 
-Consider a mapped class ``Node``, which assembles using adjacency list into a hierarchical
-tree pattern::
+Consider a mapped class ``Node``, which assembles using adjacency list
+into a hierarchical tree pattern::
 
     from sqlalchemy import Column, Integer, ForeignKey
     from sqlalchemy.orm import relationship
         parent_id = Column(Integer, ForeignKey('node.id'))
         parent = relationship("Node", remote_side=id)
 
-Suppose we wanted to add an accessor ``grandparent``.  This would return the ``parent`` of
-``Node.parent``.  When we have an instance of ``Node``, this is simple::
+Suppose we wanted to add an accessor ``grandparent``.  This would
+return the ``parent`` of ``Node.parent``.  When we have an instance of
+``Node``, this is simple::
 
     from sqlalchemy.ext.hybrid import hybrid_property
 
         def grandparent(self):
             return self.parent.parent
 
-For the expression, things are not so clear.   We'd need to construct a :class:`.Query` where we
-:meth:`~.Query.join` twice along ``Node.parent`` to get to the ``grandparent``.   We can instead
-return a transforming callable that we'll combine with the :class:`.Comparator` class
-to receive any :class:`.Query` object, and return a new one that's joined to the ``Node.parent``
-attribute and filtered based on the given criterion::
+For the expression, things are not so clear.   We'd need to construct
+a :class:`.Query` where we :meth:`~.Query.join` twice along
+``Node.parent`` to get to the ``grandparent``.   We can instead return
+a transforming callable that we'll combine with the
+:class:`.Comparator` class to receive any :class:`.Query` object, and
+return a new one that's joined to the ``Node.parent`` attribute and
+filtered based on the given criterion::
 
     from sqlalchemy.ext.hybrid import Comparator
 
         def grandparent(cls):
             return GrandparentTransformer(cls)
 
-The ``GrandparentTransformer`` overrides the core :meth:`.Operators.operate` method
-at the base of the :class:`.Comparator` hierarchy to return a query-transforming
-callable, which then runs the given comparison operation in a particular context.
-Such as, in the example above, the ``operate`` method is called, given the
-:attr:`.Operators.eq` callable as well as the right side of the comparison
-``Node(id=5)``.  A function ``transform`` is then returned which will transform
-a :class:`.Query` first to join to ``Node.parent``, then to compare ``parent_alias``
-using :attr:`.Operators.eq` against the left and right sides, passing into
-:class:`.Query.filter`:
+The ``GrandparentTransformer`` overrides the core
+:meth:`.Operators.operate` method at the base of the
+:class:`.Comparator` hierarchy to return a query-transforming
+callable, which then runs the given comparison operation in a
+particular context. Such as, in the example above, the ``operate``
+method is called, given the :attr:`.Operators.eq` callable as well as
+the right side of the comparison ``Node(id=5)``.  A function
+``transform`` is then returned which will transform a :class:`.Query`
+first to join to ``Node.parent``, then to compare ``parent_alias``
+using :attr:`.Operators.eq` against the left and right sides, passing
+into :class:`.Query.filter`:
 
 .. sourcecode:: pycon+sql
 
 
     """
 
-
     def __init__(self, func, expr=None):
         """Create a new :class:`.hybrid_method`.
 
             return self.func.__get__(instance, owner)
 
     def expression(self, expr):
-        """Provide a modifying decorator that defines a SQL-expression producing method."""
+        """Provide a modifying decorator that defines a
+        SQL-expression producing method."""
 
         self.expr = expr
         return self
         return self
 
     def deleter(self, fdel):
-        """Provide a modifying decorator that defines a value-deletion method."""
+        """Provide a modifying decorator that defines a
+        value-deletion method."""
 
         self.fdel = fdel
         return self
 
     def expression(self, expr):
-        """Provide a modifying decorator that defines a SQL-expression producing method."""
+        """Provide a modifying decorator that defines a SQL-expression
+        producing method."""
 
         self.expr = expr
         return self
 
     def comparator(self, comparator):
-        """Provide a modifying decorator that defines a custom comparator producing method.
+        """Provide a modifying decorator that defines a custom
+        comparator producing method.
 
         The return value of the decorated method should be an instance of
         :class:`~.hybrid.Comparator`.
 
         proxy_attr = attributes.\
                         create_proxied_attribute(self)
+
         def expr(owner):
             return proxy_attr(owner, self.__name__, self, comparator(owner))
         self.expr = expr
         return self
 
 class Comparator(interfaces.PropComparator):
-    """A helper class that allows easy construction of custom :class:`~.orm.interfaces.PropComparator`
+    """A helper class that allows easy construction of custom
+    :class:`~.orm.interfaces.PropComparator`
     classes for usage with hybrids."""
 
     property = None
     def adapted(self, adapter):
         # interesting....
         return self
-
-