root / elixir / tags / 0.7.0 / elixir / options.py

Revision 484, 13.8 kB (checked in by ged, 4 years ago)

update all web links

Line 
1'''
2This module provides support for defining several options on your Elixir
3entities.  There are three different kinds of options that can be set
4up, and for this there are three different statements: using_options_,
5using_table_options_ and using_mapper_options_.
6
7Alternatively, these options can be set on all Elixir entities by modifying
8the `options_defaults` dictionary before defining any entity.
9
10`using_options`
11---------------
12The 'using_options' DSL statement allows you to set up some additional
13behaviors on your model objects, including table names, ordering, and
14more.  To specify an option, simply supply the option as a keyword
15argument onto the statement, as follows:
16
17.. sourcecode:: python
18
19    class Person(Entity):
20        name = Field(Unicode(64))
21
22        using_options(shortnames=True, order_by='name')
23The list of supported arguments are as follows:
24
25+---------------------+-------------------------------------------------------+
26| Option Name         | Description                                           |
27+=====================+=======================================================+
28| ``inheritance``     | Specify the type of inheritance this entity must use. |
29|                     | It can be one of ``single``, ``concrete`` or          |
30|                     | ``multi``. Defaults to ``single``.                    |
31|                     | Note that polymorphic concrete inheritance is         |
32|                     | currently not implemented. See:                       |
33|                     | http://www.sqlalchemy.org/docs/05/mappers.html        |
34|                     | #mapping-class-inheritance-hierarchies for an         |
35|                     | explanation of the different kinds of inheritances.   |
36+---------------------+-------------------------------------------------------+
37| ``polymorphic``     | Whether the inheritance should be polymorphic or not. |
38|                     | Defaults to ``True``. The column used to store the    |
39|                     | type of each row is named "row_type" by default. You  |
40|                     | can change this by passing the desired name for the   |
41|                     | column to this argument.                              |
42+---------------------+-------------------------------------------------------+
43| ``identity``        | Specify a custom polymorphic identity. When using     |
44|                     | polymorphic inheritance, this value (usually a        |
45|                     | string) will represent this particular entity (class) |
46|                     | . It will be used to differentiate it from other      |
47|                     | entities (classes) in your inheritance hierarchy when |
48|                     | loading from the database instances of different      |
49|                     | entities in that hierarchy at the same time.          |
50|                     | This value will be stored by default in the           |
51|                     | "row_type" column of the entity's table (see above).  |
52|                     | You can either provide a                              |
53|                     | plain string or a callable. The callable will be      |
54|                     | given the entity (ie class) as argument and must      |
55|                     | return a value (usually a string) representing the    |
56|                     | polymorphic identity of that entity.                  |
57|                     | By default, this value is automatically generated: it |
58|                     | is the name of the entity lower-cased.                |
59+---------------------+-------------------------------------------------------+
60| ``metadata``        | Specify a custom MetaData for this entity.            |
61|                     | By default, entities uses the global                  |
62|                     | ``elixir.metadata``.                                  |
63|                     | This option can also be set for all entities of a     |
64|                     | module by setting the ``__metadata__`` attribute of   |
65|                     | that module.                                          |
66+---------------------+-------------------------------------------------------+
67| ``autoload``        | Automatically load column definitions from the        |
68|                     | existing database table.                              |
69+---------------------+-------------------------------------------------------+
70| ``tablename``       | Specify a custom tablename. You can either provide a  |
71|                     | plain string or a callable. The callable will be      |
72|                     | given the entity (ie class) as argument and must      |
73|                     | return a string representing the name of the table    |
74|                     | for that entity. By default, the tablename is         |
75|                     | automatically generated: it is a concatenation of the |
76|                     | full module-path to the entity and the entity (class) |
77|                     | name itself. The result is lower-cased and separated  |
78|                     | by underscores ("_"), eg.: for an entity named        |
79|                     | "MyEntity" in the module "project1.model", the        |
80|                     | generated table name will be                          |
81|                     | "project1_model_myentity".                            |
82+---------------------+-------------------------------------------------------+
83| ``shortnames``      | Specify whether or not the automatically generated    |
84|                     | table names include the full module-path              |
85|                     | to the entity. If ``shortnames`` is ``True``, only    |
86|                     | the entity name is used. Defaults to ``False``.       |
87+---------------------+-------------------------------------------------------+
88| ``auto_primarykey`` | If given as string, it will represent the             |
89|                     | auto-primary-key's column name.  If this option       |
90|                     | is True, it will allow auto-creation of a primary     |
91|                     | key if there's no primary key defined for the         |
92|                     | corresponding entity.  If this option is False,       |
93|                     | it will disallow auto-creation of a primary key.      |
94|                     | Defaults to ``True``.                                 |
95+---------------------+-------------------------------------------------------+
96| ``version_id_col``  | If this option is True, it will create a version      |
97|                     | column automatically using the default name. If given |
98|                     | as string, it will create the column using that name. |
99|                     | This can be used to prevent concurrent modifications  |
100|                     | to the entity's table rows (i.e. it will raise an     |
101|                     | exception if it happens). Defaults to ``False``.      |
102+---------------------+-------------------------------------------------------+
103| ``order_by``        | How to order select results. Either a string or a     |
104|                     | list of strings, composed of the field name,          |
105|                     | optionally lead by a minus (for descending order).    |
106+---------------------+-------------------------------------------------------+
107| ``session``         | Specify a custom contextual session for this entity.  |
108|                     | By default, entities uses the global                  |
109|                     | ``elixir.session``.                                   |
110|                     | This option takes a ``ScopedSession`` object or       |
111|                     | ``None``. In the later case your entity will be       |
112|                     | mapped using a non-contextual mapper which requires   |
113|                     | manual session management, as seen in pure SQLAlchemy.|
114|                     | This option can also be set for all entities of a     |
115|                     | module by setting the ``__session__`` attribute of    |
116|                     | that module.                                          |
117+---------------------+-------------------------------------------------------+
118| ``autosetup``       | DEPRECATED. Specify whether that entity will contain  |
119|                     | automatic setup triggers.                             |
120|                     | That is if this entity will be                        |
121|                     | automatically setup (along with all other entities    |
122|                     | which were already declared) if any of the following  |
123|                     | condition happen: some of its attributes are accessed |
124|                     | ('c', 'table', 'mapper' or 'query'), instanciated     |
125|                     | (called) or the create_all method of this entity's    |
126|                     | metadata is called. Defaults to ``False``.            |
127+---------------------+-------------------------------------------------------+
128| ``allowcoloverride``| Specify whether it is allowed to override columns.    |
129|                     | By default, Elixir forbids you to add a column to an  |
130|                     | entity's table which already exist in that table. If  |
131|                     | you set this option to ``True`` it will skip that     |
132|                     | check. Use with care as it is easy to shoot oneself   |
133|                     | in the foot when overriding columns.                  |
134+---------------------+-------------------------------------------------------+
135
136For examples, please refer to the examples and unit tests.
137
138`using_table_options`
139---------------------
140The 'using_table_options' DSL statement allows you to set up some
141additional options on your entity table. It is meant only to handle the
142options which are not supported directly by the 'using_options' statement.
143By opposition to the 'using_options' statement, these options are passed
144directly to the underlying SQLAlchemy Table object (both non-keyword arguments
145and keyword arguments) without any processing.
146
147For further information, please refer to the `SQLAlchemy table's documentation
148<http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/schema.html
149#sqlalchemy.schema.Table>`_.
150
151You might also be interested in the section about `constraints
152<http://www.sqlalchemy.org/docs/05/metadata.html
153#defining-constraints-and-indexes>`_.
154
155`using_mapper_options`
156----------------------
157The 'using_mapper_options' DSL statement allows you to set up some
158additional options on your entity mapper. It is meant only to handle the
159options which are not supported directly by the 'using_options' statement.
160By opposition to the 'using_options' statement, these options are passed
161directly to the underlying SQLAlchemy mapper (as keyword arguments)
162without any processing.
163
164For further information, please refer to the `SQLAlchemy mapper
165function's documentation
166<http://www.sqlalchemy.org/docs/05/reference/orm/mapping.html
167#sqlalchemy.orm.mapper>`_.
168
169`using_options_defaults`
170------------------------
171The 'using_options_defaults' DSL statement allows you to set up some
172default options on a custom base class. These will be used as the default value
173for options of all its subclasses. Note that any option not set within the
174using_options_defaults (nor specifically on a particular Entity) will use the
175global defaults, so you don't have to provide a default value for all options,
176but only those you want to change.
177
178'''
179
180from sqlalchemy import Integer, String
181
182from elixir.statements import ClassMutator
183
184__doc_all__ = ['options_defaults']
185
186OLD_M2MCOL_NAMEFORMAT = "%(tablename)s_%(key)s%(numifself)s"
187ALTERNATE_M2MCOL_NAMEFORMAT = "%(inversename)s_%(key)s"
188
189def default_m2m_column_formatter(data):
190    if data['selfref']:
191        return ALTERNATE_M2MCOL_NAMEFORMAT % data
192    else:
193        return OLD_M2MCOL_NAMEFORMAT % data
194
195NEW_M2MCOL_NAMEFORMAT = default_m2m_column_formatter
196
197# format constants
198FKCOL_NAMEFORMAT = "%(relname)s_%(key)s"
199M2MCOL_NAMEFORMAT = NEW_M2MCOL_NAMEFORMAT
200CONSTRAINT_NAMEFORMAT = "%(tablename)s_%(colnames)s_fk"
201MULTIINHERITANCECOL_NAMEFORMAT = "%(entity)s_%(key)s"
202
203# other global constants
204DEFAULT_AUTO_PRIMARYKEY_NAME = "id"
205DEFAULT_AUTO_PRIMARYKEY_TYPE = Integer
206DEFAULT_VERSION_ID_COL_NAME = "row_version"
207DEFAULT_POLYMORPHIC_COL_NAME = "row_type"
208POLYMORPHIC_COL_SIZE = 40
209POLYMORPHIC_COL_TYPE = String(POLYMORPHIC_COL_SIZE)
210
211# debugging/migration help
212MIGRATION_TO_07_AID = False
213
214#
215options_defaults = dict(
216    autosetup=False,
217    inheritance='single',
218    polymorphic=True,
219    identity=None,
220    autoload=False,
221    tablename=None,
222    shortnames=False,
223    auto_primarykey=True,
224    version_id_col=False,
225    allowcoloverride=False,
226    order_by=None,
227    mapper_options={},
228    table_options={}
229)
230
231valid_options = options_defaults.keys() + [
232    'metadata',
233    'session',
234    'collection'
235]
236
237
238def using_options_defaults_handler(entity, **kwargs):
239    for kwarg in kwargs:
240        if kwarg not in valid_options:
241            raise Exception("'%s' is not a valid option for Elixir entities."
242                            % kwarg)
243
244    entity.options_defaults = kwargs
245
246
247def using_options_handler(entity, *args, **kwargs):
248    for kwarg in kwargs:
249        if kwarg in valid_options:
250            setattr(entity._descriptor, kwarg, kwargs[kwarg])
251        else:
252            raise Exception("'%s' is not a valid option for Elixir entities."
253                            % kwarg)
254
255
256def using_table_options_handler(entity, *args, **kwargs):
257    entity._descriptor.table_args = list(args)
258    entity._descriptor.table_options.update(kwargs)
259
260
261def using_mapper_options_handler(entity, *args, **kwargs):
262    entity._descriptor.mapper_options.update(kwargs)
263
264
265using_options_defaults = ClassMutator(using_options_defaults_handler)
266using_options = ClassMutator(using_options_handler)
267using_table_options = ClassMutator(using_table_options_handler)
268using_mapper_options = ClassMutator(using_mapper_options_handler)
Note: See TracBrowser for help on using the browser.