Changeset 238

Show
Ignore:
Timestamp:
10/23/07 14:06:06 (7 years ago)
Author:
ged
Message:

- added support for synonym properties (on Field)
- updated TODO

Location:
elixir/trunk
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/CHANGES

    r211 r238  
    44  what is found in other Python ORM's. The with_fields syntax is now 
    55  deprecated in favor of a that new syntax. The old statement based (has_field  
    6   et al.) syntax stays the default for now. This was done with help from a  
    7   patch by Adam Gomaa. 
     6  et al.) syntax is still available though (and will remain so for quite some 
     7  time). This was done with help from a patch by Adam Gomaa. 
    88- Implemented polymorphic single-table inheritance as well as polymorphic and 
    99  non-polymorphic multi-table (aka joined table) inheritance. 
    1010- Added a .query attribute on all entities. The old .query() syntax is still 
    1111  available. 
    12 - Added support for "manual session management" (ie you can now define an  
    13   entity with "using_options(session=None)" and it won't use any 
    14   SessionContext extension, nor receive the "query" attribute. 
    1512- Added ext sub-package for additional Elixir statements. 
    1613- Added ext.associable for generating polymorphic associations with Elixir 
    1714  statements. 
    1815- versioning, encrypt ext [TODO] 
     16- Added support for synonym properties. 
     17- Added shortcut syntax to define column_properties. 
    1918- Added has_property statement to add properties on the entity mapper which 
    2019  rely on columns (an thus need them to be defined before the property can be 
    2120  declared). See tests/test_has_property.py for an example. 
     21- Added support for "manual session management" (ie you can now define an  
     22  entity with "using_options(session=None)" and it won't use any 
     23  SessionContext extension, nor receive the "query" attribute. 
    2224- Made the statement system more powerfull. 
    2325 
    2426Changes: 
     27- Autodelay and init order changed => order_by + belongs_to, belongs_to + pk,  
     28  ... [TODO] 
    2529- Made Elixir work with both SQLAlchemy 0.4 and 0.3.10 (with help from a patch 
    2630  by Ants Aasma). 
     
    3539  themselves in addition to the class namees. Obviously, this doesn't work for 
    3640  forward references. 
    37 - Autodelay and init order changed => order_by + belongs_to, belongs_to + pk,  
    38   ... [TODO] 
    3941- Classes defined inside a function can now have relationships to each other. 
    4042- Added default __init__ method on entities so that subclasses can override it 
  • elixir/trunk/TODO

    r218 r238  
    1616    - required fields 
    1717    - multiple files (modules) models 
     18    - inheritance 
    1819    - demonstrate common entities options (tablename, order_by, ...) 
    1920    - demonstrate common raltionships options (order_by, ...) 
     
    2122      show select and get_by and we don't really explain what they do). 
    2223    - explain what's the objectstore and how to use it. 
    23     ? many2many with intermediary object (extra fields in table) -> FAQ? 
     24    - autoload 
     25    - many2many with intermediary object (extra fields in table) -> FAQ? 
     26      -> tags with created_by 
     27 
    2428    ? transactions 
    2529    ? table constraints 
    26     ? autoload 
    2730    ? multi-thread 
    2831    ? multi-database 
    2932    ? deferred fields 
    30  
    31 - complete the FAQ 
    32  
    33 - document basic Types (at least link to the SQLAlchemy page listing available 
    34   types) 
    3533 
    3634- document SA/Elixir differences 
     
    3836Code related 
    3937------------ 
    40  
    41 - change setup order so that you can order_by a column created by a belongs_to 
    42   relationship. 
    43  
    44 - check that relations/fields setup with through kwargs endup with correct type 
    45   and cardinality (using a finalize method in HasField and Relationship) 
    4638 
    4739- make it possible to make a relation to an SA-mapped class (add test case) 
     
    5345  (it works but we need a proper test for that). 
    5446 
    55 - support Overriding Column Names and wrapping column in python properties 
    56   http://www.sqlalchemy.org/docs/adv_datamapping.html#advdatamapping_properties_overriding 
    57   (ie support synonym). 
    58  
    59 - implement other types of inheritance. Some of the work should be done on 
    60   SQLAlchemy's side. 
    61     cfr mailing list. 
    62  
    6347- make elixir work with migrate (or vice-versa).  
    6448    cfr mailing list 
     
    6650- test multi-col-primary-keys: we've implemented the functionality in many 
    6751  places, but we do not have a single test for that case. 
    68  
    69 - Pop relations' keyword arguments (and raise an exception) which would 
    70   conflict with those we generate 
    7152 
    7253- fix inherit VS no field in parent. You should be able to define a base 
     
    8263  the is_inverse method of the HasAndBelongsToMany class)... 
    8364 
     65- elixir on arbitrary selects. Shouldn't be hard... 
     66    cfr http://www.sqlalchemy.org/trac/ticket/502 
     67 
    8468 
    8569IDEAS 
     
    8973discussed before doing anything. 
    9074 
    91 - provide optional __init__ kwargs validation (cfr. assignmapper) 
     75- check that relations/fields setup with through kwargs endup with correct type 
     76  and cardinality (using a finalize method in HasField and Relationship) 
    9277 
    93 - provide optional "runtime setattr" validation 
     78- provide optional __init__ kwargs validation (cfr. assignmapper) (as a 
     79  recipe) 
     80 
     81- provide optional "runtime setattr" validation (as a recipe?) 
    9482  http://www.sqlalchemy.org/trac/attachment/ticket/547 
    9583  * the provided "_find_class_descriptor" seem overly complex though 
     
    9785    Entity) defines a property will probably fail because of line 16. 
    9886 
    99 - I'm not sure it would be worth it but we might want to put a section 
    100   "contributing" on the website. In that case it might be a good idea to point 
    101   to this file so that people know what can be done. 
    102  
    10387- add __revision__ (+ svn property) to all elixir files? 
    104  
    105 - implement something like: 
    106  
    107     class A(Entity): 
    108         has_many('b', of_kind='B') 
    109         has_many('b_filtered', of_kind='B', filter="extra < 10") 
    110     class B(Entity): 
    111         has_field('extra', Integer) 
    112         belongs_to('a', of_kind='A') 
    11388 
    11489- support all mapper arguments which take column arguments in a generic way 
     
    140115  instead of the acts_as_taggable Jonathan demonstrated 
    141116   
    142 - elixir on arbitrary selects. Shouldn't be hard... 
    143     cfr http://www.sqlalchemy.org/trac/ticket/502 
     117- implement something like: 
    144118 
    145 - better support from strange relation, or even other properties (like 
    146   column_property, and so on) 
    147   see http://www.sqlalchemy.org/trac/ticket/198 
     119    class A(Entity): 
     120        has_many('b', of_kind='B') 
     121        has_many('b_filtered', of_kind='B', filter=lambda c: c.extra < 10) 
     122    class B(Entity): 
     123        has_field('extra', Integer) 
     124        belongs_to('a', of_kind='A') 
    148125 
    149 - somehow support things like described at: 
     126  this is the more or less the same as what is described at: 
     127 
    150128  http://spyced.blogspot.com/2007/01/why-sqlalchemy-impresses-me.html 
    151129  ie relations using any "selectable" instead of the normal object table. 
  • elixir/trunk/elixir/entity.py

    r236 r238  
    11''' 
    2 Entity baseclass, metaclass and descriptor 
     2This module provides the ``Entity`` base class, as well as its metaclass 
     3``EntityMeta``. 
    34''' 
    45 
  • elixir/trunk/elixir/fields.py

    r236 r238  
    1616    class Person(Entity): 
    1717        id = Field(Integer, primary_key=True) 
    18         name = Field(String(50)) 
     18        name = Field(String(50), required=True) 
     19        biography = Field(String) 
     20        photo = Field(Binary, deferred=True) 
     21        _email = Field(String(20), colname='email', synonym='email') 
     22 
     23        def _set_email(self, email): 
     24           self._email = email 
     25        def _get_email(self): 
     26           return self._email 
     27        email = property(_get_email, _set_email) 
    1928 
    2029 
     
    5665|                   | ``deferred`` = `"group_name"`).                         | 
    5766+-------------------+---------------------------------------------------------+ 
     67| ``synonym``       | Specify a synonym name for this field. The field will   | 
     68|                   | also be usable under that name in keyword-based Query   | 
     69|                   | functions such as filter_by.                            | 
     70+-------------------+---------------------------------------------------------+ 
    5871 
    5972has_field 
     
    118131 
    119132from sqlalchemy import Column 
    120 from sqlalchemy.orm import deferred 
     133from sqlalchemy.orm import deferred, synonym 
    121134from sqlalchemy.ext.associationproxy import association_proxy 
    122135 
     
    141154         
    142155        self.colname = kwargs.pop('colname', None) 
     156        self.synonym = kwargs.pop('synonym', None) 
    143157        self.deferred = kwargs.pop('deferred', False) 
    144158        if 'required' in kwargs: 
     
    185199            self.entity.mapper.add_property(self.name, self.property) 
    186200 
     201        if self.synonym: 
     202            self.entity.mapper.add_property(self.synonym, synonym(self.name)) 
    187203 
    188204 
  • elixir/trunk/tests/test_properties.py

    r234 r238  
    5454                assert tag.query_score3 == tag.prop_score + 2 
    5555 
     56    def test_synonym(self): 
     57        class Person(Entity): 
     58            name = Field(String(50), required=True) 
     59            _email = Field(String(20), colname='email', synonym='email') 
    5660 
     61            def _set_email(self, email): 
     62                Person.email_values.append(email) 
     63                self._email = email 
     64 
     65            def _get_email(self): 
     66                Person.email_gets += 1 
     67                return self._email 
     68 
     69            email = property(_get_email, _set_email) 
     70            email_values = [] 
     71            email_gets = 0 
     72 
     73        setup_all(True) 
     74 
     75        mrx = Person(name='Mr. X', email='x@y.com') 
     76 
     77        assert mrx.email == 'x@y.com' 
     78        assert Person.email_gets == 1 
     79 
     80        mrx.email = "x@z.com" 
     81 
     82        assert Person.email_values == ['x@y.com', 'x@z.com'] 
     83 
     84        session.flush() 
     85        session.clear() 
     86        
     87        p = Person.get_by(email='x@z.com') 
     88         
     89        assert p.name == 'Mr. X' 
     90