root / elixir / trunk / elixir / options.py @ 185

Revision 185, 7.5 kB (checked in by cleverdevil, 6 years ago)

Patch from Mike Bayer:

The attached patch modifies Elixir's "Objectstore" implementation to work
for a SessionContext from versions 0.3 and 0.4, as well as the
0.4-onlyScopedSession object. Additionally, a new using_options() option
"session" is added, such that any user-defined SessionContext or
ScopedSession may be assigned to an Elixir class individually. So the
contextual "Session" which is to be used by Elixir can now be set at three
levels; globally using elixir.objectstore, per-module using module.session,
or per-class using using_options(session=somesess).


Three tests are added, two of which test using_options(session) against

both kinds of session, and a third which tests module-level usage of
ScopedSession.


At the very least, the new "Objectstore" class should be implemented which

establishes compatibility with ScopedSession which is featured in the Pylons
tutorial.


the patch also fixes a bug in versioned.py where an execute() statement
could be issued using unicode keywords, which is illegal for the **params
calling style.

Thanks, Mike!


Line 
1'''
2Option statements for Elixir entities
3
4=======
5Options
6=======
7
8This module provides DSL statements for defining options on your Elixir
9entities.  There are three different kinds of options that can be set
10up, and for this there are three different statements: using_options_,
11using_table_options_ and using_mapper_options_.
12Alternatively, options can be set on all Elixir entities by modifying the
13`options_defaults` dictionary before defining any entity.
14
15`using_options`
16---------------
17The 'using_options' DSL statement allows you to set up some additional
18behaviors on your model objects, including table names, ordering, and
19more.  To specify an option, simply supply the option as a keyword
20argument onto the statement, as follows:
21
22::
23
24    class Person(Entity):
25        has_field('name', Unicode(64))
26
27        using_options(shortnames=True, order_by='name')
28
29The list of supported arguments are as follows:
30
31+---------------------+-------------------------------------------------------+
32| Option Name         | Description                                           |
33+=====================+=======================================================+
34| ``inheritance``     | Specify the type of inheritance this entity must use. |
35|                     | It can be one of ``single``, ``concrete`` or          |
36|                     | ``multi``. Defaults to ``single``.                    |
37+---------------------+-------------------------------------------------------+
38| ``polymorphic``     | Whether the inheritance should be polymorphic or not. |
39|                     | Defaults to ``False``. Note that polymorphic concrete |
40|                     | inheritance is currently not implemented.             |
41+---------------------+-------------------------------------------------------+
42| ``metadata``        | Specify a custom MetaData.                            |
43+---------------------+-------------------------------------------------------+
44| ``autoload``        | Automatically load column definitions from the        |
45|                     | existing database table.                              |
46+---------------------+-------------------------------------------------------+
47| ``tablename``       | Specify a custom tablename. You can either provide a  |
48|                     | plain string or a callable. The callable will be      |
49|                     | given the entity (ie class) as argument and must      |
50|                     | return a string representing the name of the table    |
51|                     | for that entity.                                      |
52+---------------------+-------------------------------------------------------+
53| ``shortnames``      | Usually tablenames include the full module-path       |
54|                     | to the entity, but lower-cased and separated by       |
55|                     | underscores ("_"), eg.: "project1_model_myentity"     |
56|                     | for an entity named "MyEntity" in the module          |
57|                     | "project1.model".  If shortnames is ``True``, the     |
58|                     | tablename will just be the entity's classname         |
59|                     | lower-cased, ie. "myentity".                          |
60+---------------------+-------------------------------------------------------+
61| ``auto_primarykey`` | If given as string, it will represent the             |
62|                     | auto-primary-key's column name.  If this option       |
63|                     | is True, it will allow auto-creation of a primary     |
64|                     | key if there's no primary key defined for the         |
65|                     | corresponding entity.  If this option is False,       |
66|                     | it will disallow auto-creation of a primary key.      |
67+---------------------+-------------------------------------------------------+
68| ``version_id_col``  | If this option is True, it will create a version      |
69|                     | column automatically using the default name. If given |
70|                     | as string, it will create the column using that name. |
71|                     | This can be used to prevent concurrent modifications  |
72|                     | to the entity's table rows (i.e. it will raise an     |
73|                     | exception if it happens).                             |
74+---------------------+-------------------------------------------------------+
75| ``order_by``        | How to order select results. Either a string or a     |
76|                     | list of strings, composed of the field name,          |
77|                     | optionally lead by a minus (descending order).        |
78+---------------------+-------------------------------------------------------+
79
80For examples, please refer to the examples and unit tests.
81
82`using_table_options`
83---------------------
84The 'using_table_options' DSL statement allows you to set up some
85additional options on your entity table. It is meant only to handle the
86options which are not supported directly by the 'using_options' statement.
87By opposition to the 'using_options' statement, these options are passed
88directly to the underlying SQLAlchemy Table object (both non-keyword arguments
89and keyword arguments) without any processing.
90
91For further information, please refer to the `SQLAlchemy table's documentation
92<http://www.sqlalchemy.org/docs/docstrings.myt
93#docstrings_sqlalchemy.schema_Table>`_.
94
95You might also be interested in the section about `constraints
96<http://www.sqlalchemy.org/docs/metadata.myt#metadata_constraints>`_.
97
98`using_mapper_options`
99----------------------
100The 'using_mapper_options' DSL statement allows you to set up some
101additional options on your entity mapper. It is meant only to handle the
102options which are not supported directly by the 'using_options' statement.
103By opposition to the 'using_options' statement, these options are passed
104directly to the underlying SQLAlchemy mapper (as keyword arguments)
105without any processing.
106
107For further information, please refer to the `SQLAlchemy mapper
108function's documentation <http://www.sqlalchemy.org/docs/adv_datamapping.myt
109#advdatamapping_mapperoptions>`_.
110'''
111
112from elixir.statements import Statement
113
114__pudge_all__ = ['options_defaults']
115
116options_defaults = dict(
117    inheritance='single',
118    polymorphic=False,
119    autoload=None,
120    shortnames=False,
121    tablename=None,
122    auto_primarykey=True,
123    version_id_col=False,
124    mapper_options=dict(),
125    table_options=dict(),
126)
127
128class UsingOptions(object):   
129    valid_options = (
130        'inheritance',
131        'polymorphic',
132        'autoload',
133        'tablename',
134        'shortnames',
135        'auto_primarykey',
136        'version_id_col',
137        'metadata',
138        'order_by',
139        'session',
140    )
141   
142    def __init__(self, entity, *args, **kwargs):
143        desc = entity._descriptor
144       
145        for kwarg in kwargs:
146            if kwarg in UsingOptions.valid_options:
147                setattr(desc, kwarg, kwargs[kwarg])
148            else:
149                raise Exception("'%s' is not a valid option for Elixir "
150                                "entities." % kwarg)
151
152
153class UsingTableOptions(object):
154
155    def __init__(self, entity, *args, **kwargs):
156        entity._descriptor.table_args = list(args)
157        entity._descriptor.table_options.update(kwargs)
158
159
160class UsingMapperOptions(object):
161
162    def __init__(self, entity, *args, **kwargs):
163        entity._descriptor.mapper_options.update(kwargs)
164
165
166using_options = Statement(UsingOptions)
167using_table_options = Statement(UsingTableOptions)
168using_mapper_options = Statement(UsingMapperOptions)
Note: See TracBrowser for help on using the browser.