root / elixir / tags / 0.6.0 / elixir / options.py

Revision 349, 12.4 kB (checked in by ged, 4 years ago)

- The default session (elixir.session) uses sessionmaker() instead of

create_session(), which means it has now the following characterisics:

  • autoflush=True
  • autocommit=False (with SA 0.5 -- equivalent to transactional=True with
    SA 0.4)
  • autoexpire=True (with SA 0.5).

- Removed objectstore and some other old cruft (mostly SA 0.3 or earlier

support code)

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')
23
24The list of supported arguments are as follows:
25
26+---------------------+-------------------------------------------------------+
27| Option Name         | Description                                           |
28+=====================+=======================================================+
29| ``inheritance``     | Specify the type of inheritance this entity must use. |
30|                     | It can be one of ``single``, ``concrete`` or          |
31|                     | ``multi``. Defaults to ``single``.                    |
32|                     | Note that polymorphic concrete inheritance is         |
33|                     | currently not implemented. See:                       |
34|                     | http://www.sqlalchemy.org/docs/04/mappers.html        |
35|                     | #advdatamapping_mapper_inheritance for an explanation |
36|                     | of the different kinds of inheritances.               |
37+---------------------+-------------------------------------------------------+
38| ``polymorphic``     | Whether the inheritance should be polymorphic or not. |
39|                     | Defaults to ``True``. The column used to store the    |
40|                     | type of each row is named "row_type" by default. You  |
41|                     | can change this by passing the desired name for the   |
42|                     | column to this argument.                              |
43+---------------------+-------------------------------------------------------+
44| ``identity``        | Specify a custom polymorphic identity. When using     |
45|                     | polymorphic inheritance, this value (usually a        |
46|                     | string) will represent this particular entity (class) |
47|                     | . It will be used to differentiate it from other      |
48|                     | entities (classes) in your inheritance hierarchy when |
49|                     | loading from the database instances of different      |
50|                     | entities in that hierarchy at the same time.          |
51|                     | This value will be stored by default in the           |
52|                     | "row_type" column of the entity's table (see above).  |
53|                     | You can either provide a                              |
54|                     | plain string or a callable. The callable will be      |
55|                     | given the entity (ie class) as argument and must      |
56|                     | return a value (usually a string) representing the    |
57|                     | polymorphic identity of that entity.                  |
58|                     | By default, this value is automatically generated: it |
59|                     | is the name of the entity lower-cased.                |
60+---------------------+-------------------------------------------------------+
61| ``metadata``        | Specify a custom MetaData for this entity.            |
62|                     | By default, entities uses the global                  |
63|                     | ``elixir.metadata``.                                  |
64|                     | This option can also be set for all entities of a     |
65|                     | module by setting the ``__metadata__`` attribute of   |
66|                     | that module.                                          |
67+---------------------+-------------------------------------------------------+
68| ``autoload``        | Automatically load column definitions from the        |
69|                     | existing database table.                              |
70+---------------------+-------------------------------------------------------+
71| ``tablename``       | Specify a custom tablename. You can either provide a  |
72|                     | plain string or a callable. The callable will be      |
73|                     | given the entity (ie class) as argument and must      |
74|                     | return a string representing the name of the table    |
75|                     | for that entity. By default, the tablename is         |
76|                     | automatically generated: it is a concatenation of the |
77|                     | full module-path to the entity and the entity (class) |
78|                     | name itself. The result is lower-cased and separated  |
79|                     | by underscores ("_"), eg.: for an entity named        |
80|                     | "MyEntity" in the module "project1.model", the        |
81|                     | generated table name will be                          |
82|                     | "project1_model_myentity".                            |
83+---------------------+-------------------------------------------------------+
84| ``shortnames``      | Specify whether or not the automatically generated    |
85|                     | table names include the full module-path              |
86|                     | to the entity. Defaults to ``True``.                  |
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                                        |
113|                     | non-contextual mapper. This option can also be set    |
114|                     | for all entities of a module by setting the           |
115|                     | ``__session__`` attribute of that module.             |
116+---------------------+-------------------------------------------------------+
117| ``autosetup``       | Specify whether that entity will contain automatic    |
118|                     | setup triggers. That is if this entity will be        |
119|                     | automatically setup (along with all other entities    |
120|                     | which were already declared) if any of the following  |
121|                     | condition happen: some of its attributes are accessed |
122|                     | ('c', 'table', 'mapper' or 'query'), instanciated     |
123|                     | (called) or the create_all method of this entity's    |
124|                     | metadata is called. Defaults to ``False``.            |
125+---------------------+-------------------------------------------------------+
126| ``allowcoloverride``| Specify whether it is allowed to override columns.    |
127|                     | By default, Elixir forbids you to add a column to an  |
128|                     | entity's table which already exist in that table. If  |
129|                     | you set this option to ``True`` it will skip that     |
130|                     | check. Use with care as it is easy to shoot oneself   |
131|                     | in the foot when overriding columns.                  |
132+---------------------+-------------------------------------------------------+
133
134
135For examples, please refer to the examples and unit tests.
136
137`using_table_options`
138---------------------
139The 'using_table_options' DSL statement allows you to set up some
140additional options on your entity table. It is meant only to handle the
141options which are not supported directly by the 'using_options' statement.
142By opposition to the 'using_options' statement, these options are passed
143directly to the underlying SQLAlchemy Table object (both non-keyword arguments
144and keyword arguments) without any processing.
145
146For further information, please refer to the `SQLAlchemy table's documentation
147<http://www.sqlalchemy.org/docs/04/sqlalchemy_schema.html
148#docstrings_sqlalchemy.schema_Table>`_.
149
150You might also be interested in the section about `constraints
151<http://www.sqlalchemy.org/docs/04/metadata.html#metadata_constraints>`_.
152
153`using_mapper_options`
154----------------------
155The 'using_mapper_options' DSL statement allows you to set up some
156additional options on your entity mapper. It is meant only to handle the
157options which are not supported directly by the 'using_options' statement.
158By opposition to the 'using_options' statement, these options are passed
159directly to the underlying SQLAlchemy mapper (as keyword arguments)
160without any processing.
161
162For further information, please refer to the `SQLAlchemy mapper
163function's documentation
164<http://www.sqlalchemy.org/docs/04/sqlalchemy_orm.html
165#docstrings_sqlalchemy.orm_modfunc_mapper>`_.
166'''
167
168from elixir.statements import ClassMutator
169from sqlalchemy import Integer, String
170
171__doc_all__ = ['options_defaults']
172
173# format constants
174FKCOL_NAMEFORMAT = "%(relname)s_%(key)s"
175M2MCOL_NAMEFORMAT = "%(tablename)s_%(key)s"
176CONSTRAINT_NAMEFORMAT = "%(tablename)s_%(colnames)s_fk"
177MULTIINHERITANCECOL_NAMEFORMAT = "%(entity)s_%(key)s"
178
179# other global constants
180DEFAULT_AUTO_PRIMARYKEY_NAME = "id"
181DEFAULT_AUTO_PRIMARYKEY_TYPE = Integer
182DEFAULT_VERSION_ID_COL_NAME = "row_version"
183DEFAULT_POLYMORPHIC_COL_NAME = "row_type"
184POLYMORPHIC_COL_SIZE = 40
185POLYMORPHIC_COL_TYPE = String(POLYMORPHIC_COL_SIZE)
186
187#
188options_defaults = dict(
189    autosetup=False,
190    inheritance='single',
191    polymorphic=True,
192    identity=None,
193    autoload=False,
194    tablename=None,
195    shortnames=False,
196    auto_primarykey=True,
197    version_id_col=False,
198    allowcoloverride=False,
199    mapper_options=dict(),
200    table_options=dict(),
201)
202
203
204valid_options = options_defaults.keys() + [
205    'metadata',
206    'session',
207    'collection',
208    'order_by',
209]
210
211
212def using_options_handler(entity, *args, **kwargs):
213    for kwarg in kwargs:
214        if kwarg in valid_options:
215            setattr(entity._descriptor, kwarg, kwargs[kwarg])
216        else:
217            raise Exception("'%s' is not a valid option for Elixir entities."
218                            % kwarg)
219
220
221def using_table_options_handler(entity, *args, **kwargs):
222    entity._descriptor.table_args = list(args)
223    entity._descriptor.table_options.update(kwargs)
224
225
226def using_mapper_options_handler(entity, *args, **kwargs):
227    entity._descriptor.mapper_options.update(kwargs)
228
229
230using_options = ClassMutator(using_options_handler)
231using_table_options = ClassMutator(using_table_options_handler)
232using_mapper_options = ClassMutator(using_mapper_options_handler)
Note: See TracBrowser for help on using the browser.