Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# sql/types_api.py 

2# Copyright (C) 2005-2020 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: http://www.opensource.org/licenses/mit-license.php 

7 

8"""Base types API. 

9 

10""" 

11 

12 

13from . import operators 

14from .base import SchemaEventTarget 

15from .visitors import Visitable 

16from .visitors import VisitableType 

17from .. import exc 

18from .. import util 

19 

20 

21# these are back-assigned by sqltypes. 

22BOOLEANTYPE = None 

23INTEGERTYPE = None 

24NULLTYPE = None 

25STRINGTYPE = None 

26MATCHTYPE = None 

27INDEXABLE = None 

28_resolve_value_to_type = None 

29 

30 

31class TypeEngine(Visitable): 

32 """The ultimate base class for all SQL datatypes. 

33 

34 Common subclasses of :class:`.TypeEngine` include 

35 :class:`.String`, :class:`.Integer`, and :class:`.Boolean`. 

36 

37 For an overview of the SQLAlchemy typing system, see 

38 :ref:`types_toplevel`. 

39 

40 .. seealso:: 

41 

42 :ref:`types_toplevel` 

43 

44 """ 

45 

46 _sqla_type = True 

47 _isnull = False 

48 

49 class Comparator(operators.ColumnOperators): 

50 """Base class for custom comparison operations defined at the 

51 type level. See :attr:`.TypeEngine.comparator_factory`. 

52 

53 

54 """ 

55 

56 __slots__ = "expr", "type" 

57 

58 default_comparator = None 

59 

60 def __init__(self, expr): 

61 self.expr = expr 

62 self.type = expr.type 

63 

64 @util.dependencies("sqlalchemy.sql.default_comparator") 

65 def operate(self, default_comparator, op, *other, **kwargs): 

66 o = default_comparator.operator_lookup[op.__name__] 

67 return o[0](self.expr, op, *(other + o[1:]), **kwargs) 

68 

69 @util.dependencies("sqlalchemy.sql.default_comparator") 

70 def reverse_operate(self, default_comparator, op, other, **kwargs): 

71 o = default_comparator.operator_lookup[op.__name__] 

72 return o[0](self.expr, op, other, reverse=True, *o[1:], **kwargs) 

73 

74 def _adapt_expression(self, op, other_comparator): 

75 """evaluate the return type of <self> <op> <othertype>, 

76 and apply any adaptations to the given operator. 

77 

78 This method determines the type of a resulting binary expression 

79 given two source types and an operator. For example, two 

80 :class:`_schema.Column` objects, both of the type 

81 :class:`.Integer`, will 

82 produce a :class:`.BinaryExpression` that also has the type 

83 :class:`.Integer` when compared via the addition (``+``) operator. 

84 However, using the addition operator with an :class:`.Integer` 

85 and a :class:`.Date` object will produce a :class:`.Date`, assuming 

86 "days delta" behavior by the database (in reality, most databases 

87 other than PostgreSQL don't accept this particular operation). 

88 

89 The method returns a tuple of the form <operator>, <type>. 

90 The resulting operator and type will be those applied to the 

91 resulting :class:`.BinaryExpression` as the final operator and the 

92 right-hand side of the expression. 

93 

94 Note that only a subset of operators make usage of 

95 :meth:`._adapt_expression`, 

96 including math operators and user-defined operators, but not 

97 boolean comparison or special SQL keywords like MATCH or BETWEEN. 

98 

99 """ 

100 

101 return op, self.type 

102 

103 def __reduce__(self): 

104 return _reconstitute_comparator, (self.expr,) 

105 

106 hashable = True 

107 """Flag, if False, means values from this type aren't hashable. 

108 

109 Used by the ORM when uniquing result lists. 

110 

111 """ 

112 

113 comparator_factory = Comparator 

114 """A :class:`.TypeEngine.Comparator` class which will apply 

115 to operations performed by owning :class:`_expression.ColumnElement` 

116 objects. 

117 

118 The :attr:`.comparator_factory` attribute is a hook consulted by 

119 the core expression system when column and SQL expression operations 

120 are performed. When a :class:`.TypeEngine.Comparator` class is 

121 associated with this attribute, it allows custom re-definition of 

122 all existing operators, as well as definition of new operators. 

123 Existing operators include those provided by Python operator overloading 

124 such as :meth:`.operators.ColumnOperators.__add__` and 

125 :meth:`.operators.ColumnOperators.__eq__`, 

126 those provided as standard 

127 attributes of :class:`.operators.ColumnOperators` such as 

128 :meth:`.operators.ColumnOperators.like` 

129 and :meth:`.operators.ColumnOperators.in_`. 

130 

131 Rudimentary usage of this hook is allowed through simple subclassing 

132 of existing types, or alternatively by using :class:`.TypeDecorator`. 

133 See the documentation section :ref:`types_operators` for examples. 

134 

135 """ 

136 

137 sort_key_function = None 

138 """A sorting function that can be passed as the key to sorted. 

139 

140 The default value of ``None`` indicates that the values stored by 

141 this type are self-sorting. 

142 

143 .. versionadded:: 1.3.8 

144 

145 """ 

146 

147 should_evaluate_none = False 

148 """If True, the Python constant ``None`` is considered to be handled 

149 explicitly by this type. 

150 

151 The ORM uses this flag to indicate that a positive value of ``None`` 

152 is passed to the column in an INSERT statement, rather than omitting 

153 the column from the INSERT statement which has the effect of firing 

154 off column-level defaults. It also allows types which have special 

155 behavior for Python None, such as a JSON type, to indicate that 

156 they'd like to handle the None value explicitly. 

157 

158 To set this flag on an existing type, use the 

159 :meth:`.TypeEngine.evaluates_none` method. 

160 

161 .. seealso:: 

162 

163 :meth:`.TypeEngine.evaluates_none` 

164 

165 .. versionadded:: 1.1 

166 

167 

168 """ 

169 

170 def evaluates_none(self): 

171 """Return a copy of this type which has the :attr:`.should_evaluate_none` 

172 flag set to True. 

173 

174 E.g.:: 

175 

176 Table( 

177 'some_table', metadata, 

178 Column( 

179 String(50).evaluates_none(), 

180 nullable=True, 

181 server_default='no value') 

182 ) 

183 

184 The ORM uses this flag to indicate that a positive value of ``None`` 

185 is passed to the column in an INSERT statement, rather than omitting 

186 the column from the INSERT statement which has the effect of firing 

187 off column-level defaults. It also allows for types which have 

188 special behavior associated with the Python None value to indicate 

189 that the value doesn't necessarily translate into SQL NULL; a 

190 prime example of this is a JSON type which may wish to persist the 

191 JSON value ``'null'``. 

192 

193 In all cases, the actual NULL SQL value can be always be 

194 persisted in any column by using 

195 the :obj:`_expression.null` SQL construct in an INSERT statement 

196 or associated with an ORM-mapped attribute. 

197 

198 .. note:: 

199 

200 The "evaluates none" flag does **not** apply to a value 

201 of ``None`` passed to :paramref:`_schema.Column.default` or 

202 :paramref:`_schema.Column.server_default`; in these cases, 

203 ``None`` 

204 still means "no default". 

205 

206 .. versionadded:: 1.1 

207 

208 .. seealso:: 

209 

210 :ref:`session_forcing_null` - in the ORM documentation 

211 

212 :paramref:`.postgresql.JSON.none_as_null` - PostgreSQL JSON 

213 interaction with this flag. 

214 

215 :attr:`.TypeEngine.should_evaluate_none` - class-level flag 

216 

217 """ 

218 typ = self.copy() 

219 typ.should_evaluate_none = True 

220 return typ 

221 

222 def copy(self, **kw): 

223 return self.adapt(self.__class__) 

224 

225 def compare_against_backend(self, dialect, conn_type): 

226 """Compare this type against the given backend type. 

227 

228 This function is currently not implemented for SQLAlchemy 

229 types, and for all built in types will return ``None``. However, 

230 it can be implemented by a user-defined type 

231 where it can be consumed by schema comparison tools such as 

232 Alembic autogenerate. 

233 

234 A future release of SQLAlchemy will potentially implement this method 

235 for builtin types as well. 

236 

237 The function should return True if this type is equivalent to the 

238 given type; the type is typically reflected from the database 

239 so should be database specific. The dialect in use is also 

240 passed. It can also return False to assert that the type is 

241 not equivalent. 

242 

243 :param dialect: a :class:`.Dialect` that is involved in the comparison. 

244 

245 :param conn_type: the type object reflected from the backend. 

246 

247 .. versionadded:: 1.0.3 

248 

249 """ 

250 return None 

251 

252 def copy_value(self, value): 

253 return value 

254 

255 def literal_processor(self, dialect): 

256 """Return a conversion function for processing literal values that are 

257 to be rendered directly without using binds. 

258 

259 This function is used when the compiler makes use of the 

260 "literal_binds" flag, typically used in DDL generation as well 

261 as in certain scenarios where backends don't accept bound parameters. 

262 

263 .. versionadded:: 0.9.0 

264 

265 """ 

266 return None 

267 

268 def bind_processor(self, dialect): 

269 """Return a conversion function for processing bind values. 

270 

271 Returns a callable which will receive a bind parameter value 

272 as the sole positional argument and will return a value to 

273 send to the DB-API. 

274 

275 If processing is not necessary, the method should return ``None``. 

276 

277 :param dialect: Dialect instance in use. 

278 

279 """ 

280 return None 

281 

282 def result_processor(self, dialect, coltype): 

283 """Return a conversion function for processing result row values. 

284 

285 Returns a callable which will receive a result row column 

286 value as the sole positional argument and will return a value 

287 to return to the user. 

288 

289 If processing is not necessary, the method should return ``None``. 

290 

291 :param dialect: Dialect instance in use. 

292 

293 :param coltype: DBAPI coltype argument received in cursor.description. 

294 

295 """ 

296 return None 

297 

298 def column_expression(self, colexpr): 

299 """Given a SELECT column expression, return a wrapping SQL expression. 

300 

301 This is typically a SQL function that wraps a column expression 

302 as rendered in the columns clause of a SELECT statement. 

303 It is used for special data types that require 

304 columns to be wrapped in some special database function in order 

305 to coerce the value before being sent back to the application. 

306 It is the SQL analogue of the :meth:`.TypeEngine.result_processor` 

307 method. 

308 

309 The method is evaluated at statement compile time, as opposed 

310 to statement construction time. 

311 

312 .. seealso:: 

313 

314 :ref:`types_sql_value_processing` 

315 

316 """ 

317 

318 return None 

319 

320 @util.memoized_property 

321 def _has_column_expression(self): 

322 """memoized boolean, check if column_expression is implemented. 

323 

324 Allows the method to be skipped for the vast majority of expression 

325 types that don't use this feature. 

326 

327 """ 

328 

329 return ( 

330 self.__class__.column_expression.__code__ 

331 is not TypeEngine.column_expression.__code__ 

332 ) 

333 

334 def bind_expression(self, bindvalue): 

335 """"Given a bind value (i.e. a :class:`.BindParameter` instance), 

336 return a SQL expression in its place. 

337 

338 This is typically a SQL function that wraps the existing bound 

339 parameter within the statement. It is used for special data types 

340 that require literals being wrapped in some special database function 

341 in order to coerce an application-level value into a database-specific 

342 format. It is the SQL analogue of the 

343 :meth:`.TypeEngine.bind_processor` method. 

344 

345 The method is evaluated at statement compile time, as opposed 

346 to statement construction time. 

347 

348 Note that this method, when implemented, should always return 

349 the exact same structure, without any conditional logic, as it 

350 may be used in an executemany() call against an arbitrary number 

351 of bound parameter sets. 

352 

353 .. seealso:: 

354 

355 :ref:`types_sql_value_processing` 

356 

357 """ 

358 return None 

359 

360 @util.memoized_property 

361 def _has_bind_expression(self): 

362 """memoized boolean, check if bind_expression is implemented. 

363 

364 Allows the method to be skipped for the vast majority of expression 

365 types that don't use this feature. 

366 

367 """ 

368 

369 return ( 

370 self.__class__.bind_expression.__code__ 

371 is not TypeEngine.bind_expression.__code__ 

372 ) 

373 

374 @staticmethod 

375 def _to_instance(cls_or_self): 

376 return to_instance(cls_or_self) 

377 

378 def compare_values(self, x, y): 

379 """Compare two values for equality.""" 

380 

381 return x == y 

382 

383 def get_dbapi_type(self, dbapi): 

384 """Return the corresponding type object from the underlying DB-API, if 

385 any. 

386 

387 This can be useful for calling ``setinputsizes()``, for example. 

388 

389 """ 

390 return None 

391 

392 @property 

393 def python_type(self): 

394 """Return the Python type object expected to be returned 

395 by instances of this type, if known. 

396 

397 Basically, for those types which enforce a return type, 

398 or are known across the board to do such for all common 

399 DBAPIs (like ``int`` for example), will return that type. 

400 

401 If a return type is not defined, raises 

402 ``NotImplementedError``. 

403 

404 Note that any type also accommodates NULL in SQL which 

405 means you can also get back ``None`` from any type 

406 in practice. 

407 

408 """ 

409 raise NotImplementedError() 

410 

411 def with_variant(self, type_, dialect_name): 

412 r"""Produce a new type object that will utilize the given 

413 type when applied to the dialect of the given name. 

414 

415 e.g.:: 

416 

417 from sqlalchemy.types import String 

418 from sqlalchemy.dialects import mysql 

419 

420 s = String() 

421 

422 s = s.with_variant(mysql.VARCHAR(collation='foo'), 'mysql') 

423 

424 The construction of :meth:`.TypeEngine.with_variant` is always 

425 from the "fallback" type to that which is dialect specific. 

426 The returned type is an instance of :class:`.Variant`, which 

427 itself provides a :meth:`.Variant.with_variant` 

428 that can be called repeatedly. 

429 

430 :param type\_: a :class:`.TypeEngine` that will be selected 

431 as a variant from the originating type, when a dialect 

432 of the given name is in use. 

433 :param dialect_name: base name of the dialect which uses 

434 this type. (i.e. ``'postgresql'``, ``'mysql'``, etc.) 

435 

436 """ 

437 return Variant(self, {dialect_name: to_instance(type_)}) 

438 

439 @util.memoized_property 

440 def _type_affinity(self): 

441 """Return a rudimental 'affinity' value expressing the general class 

442 of type.""" 

443 

444 typ = None 

445 for t in self.__class__.__mro__: 

446 if t in (TypeEngine, UserDefinedType): 

447 return typ 

448 elif issubclass(t, (TypeEngine, UserDefinedType)): 

449 typ = t 

450 else: 

451 return self.__class__ 

452 

453 def dialect_impl(self, dialect): 

454 """Return a dialect-specific implementation for this 

455 :class:`.TypeEngine`. 

456 

457 """ 

458 try: 

459 return dialect._type_memos[self]["impl"] 

460 except KeyError: 

461 return self._dialect_info(dialect)["impl"] 

462 

463 def _unwrapped_dialect_impl(self, dialect): 

464 """Return the 'unwrapped' dialect impl for this type. 

465 

466 For a type that applies wrapping logic (e.g. TypeDecorator), give 

467 us the real, actual dialect-level type that is used. 

468 

469 This is used by TypeDecorator itself as well at least one case where 

470 dialects need to check that a particular specific dialect-level 

471 type is in use, within the :meth:`.DefaultDialect.set_input_sizes` 

472 method. 

473 

474 """ 

475 return self.dialect_impl(dialect) 

476 

477 def _cached_literal_processor(self, dialect): 

478 """Return a dialect-specific literal processor for this type.""" 

479 try: 

480 return dialect._type_memos[self]["literal"] 

481 except KeyError: 

482 pass 

483 # avoid KeyError context coming into literal_processor() function 

484 # raises 

485 d = self._dialect_info(dialect) 

486 d["literal"] = lp = d["impl"].literal_processor(dialect) 

487 return lp 

488 

489 def _cached_bind_processor(self, dialect): 

490 """Return a dialect-specific bind processor for this type.""" 

491 

492 try: 

493 return dialect._type_memos[self]["bind"] 

494 except KeyError: 

495 pass 

496 # avoid KeyError context coming into bind_processor() function 

497 # raises 

498 d = self._dialect_info(dialect) 

499 d["bind"] = bp = d["impl"].bind_processor(dialect) 

500 return bp 

501 

502 def _cached_result_processor(self, dialect, coltype): 

503 """Return a dialect-specific result processor for this type.""" 

504 

505 try: 

506 return dialect._type_memos[self][coltype] 

507 except KeyError: 

508 pass 

509 # avoid KeyError context coming into result_processor() function 

510 # raises 

511 d = self._dialect_info(dialect) 

512 # key assumption: DBAPI type codes are 

513 # constants. Else this dictionary would 

514 # grow unbounded. 

515 d[coltype] = rp = d["impl"].result_processor(dialect, coltype) 

516 return rp 

517 

518 def _cached_custom_processor(self, dialect, key, fn): 

519 try: 

520 return dialect._type_memos[self][key] 

521 except KeyError: 

522 pass 

523 # avoid KeyError context coming into fn() function 

524 # raises 

525 d = self._dialect_info(dialect) 

526 impl = d["impl"] 

527 d[key] = result = fn(impl) 

528 return result 

529 

530 def _dialect_info(self, dialect): 

531 """Return a dialect-specific registry which 

532 caches a dialect-specific implementation, bind processing 

533 function, and one or more result processing functions.""" 

534 

535 if self in dialect._type_memos: 

536 return dialect._type_memos[self] 

537 else: 

538 impl = self._gen_dialect_impl(dialect) 

539 if impl is self: 

540 impl = self.adapt(type(self)) 

541 # this can't be self, else we create a cycle 

542 assert impl is not self 

543 dialect._type_memos[self] = d = {"impl": impl} 

544 return d 

545 

546 def _gen_dialect_impl(self, dialect): 

547 return dialect.type_descriptor(self) 

548 

549 def adapt(self, cls, **kw): 

550 """Produce an "adapted" form of this type, given an "impl" class 

551 to work with. 

552 

553 This method is used internally to associate generic 

554 types with "implementation" types that are specific to a particular 

555 dialect. 

556 """ 

557 return util.constructor_copy(self, cls, **kw) 

558 

559 def coerce_compared_value(self, op, value): 

560 """Suggest a type for a 'coerced' Python value in an expression. 

561 

562 Given an operator and value, gives the type a chance 

563 to return a type which the value should be coerced into. 

564 

565 The default behavior here is conservative; if the right-hand 

566 side is already coerced into a SQL type based on its 

567 Python type, it is usually left alone. 

568 

569 End-user functionality extension here should generally be via 

570 :class:`.TypeDecorator`, which provides more liberal behavior in that 

571 it defaults to coercing the other side of the expression into this 

572 type, thus applying special Python conversions above and beyond those 

573 needed by the DBAPI to both ides. It also provides the public method 

574 :meth:`.TypeDecorator.coerce_compared_value` which is intended for 

575 end-user customization of this behavior. 

576 

577 """ 

578 _coerced_type = _resolve_value_to_type(value) 

579 if ( 

580 _coerced_type is NULLTYPE 

581 or _coerced_type._type_affinity is self._type_affinity 

582 ): 

583 return self 

584 else: 

585 return _coerced_type 

586 

587 def _compare_type_affinity(self, other): 

588 return self._type_affinity is other._type_affinity 

589 

590 def compile(self, dialect=None): 

591 """Produce a string-compiled form of this :class:`.TypeEngine`. 

592 

593 When called with no arguments, uses a "default" dialect 

594 to produce a string result. 

595 

596 :param dialect: a :class:`.Dialect` instance. 

597 

598 """ 

599 # arg, return value is inconsistent with 

600 # ClauseElement.compile()....this is a mistake. 

601 

602 if not dialect: 

603 dialect = self._default_dialect() 

604 

605 return dialect.type_compiler.process(self) 

606 

607 @util.dependencies("sqlalchemy.engine.default") 

608 def _default_dialect(self, default): 

609 if self.__class__.__module__.startswith("sqlalchemy.dialects"): 

610 tokens = self.__class__.__module__.split(".")[0:3] 

611 mod = ".".join(tokens) 

612 return getattr(__import__(mod).dialects, tokens[-1]).dialect() 

613 else: 

614 return default.DefaultDialect() 

615 

616 def __str__(self): 

617 if util.py2k: 

618 return unicode(self.compile()).encode( # noqa 

619 "ascii", "backslashreplace" 

620 ) # noqa 

621 else: 

622 return str(self.compile()) 

623 

624 def __repr__(self): 

625 return util.generic_repr(self) 

626 

627 

628class VisitableCheckKWArg(util.EnsureKWArgType, VisitableType): 

629 pass 

630 

631 

632class UserDefinedType(util.with_metaclass(VisitableCheckKWArg, TypeEngine)): 

633 """Base for user defined types. 

634 

635 This should be the base of new types. Note that 

636 for most cases, :class:`.TypeDecorator` is probably 

637 more appropriate:: 

638 

639 import sqlalchemy.types as types 

640 

641 class MyType(types.UserDefinedType): 

642 def __init__(self, precision = 8): 

643 self.precision = precision 

644 

645 def get_col_spec(self, **kw): 

646 return "MYTYPE(%s)" % self.precision 

647 

648 def bind_processor(self, dialect): 

649 def process(value): 

650 return value 

651 return process 

652 

653 def result_processor(self, dialect, coltype): 

654 def process(value): 

655 return value 

656 return process 

657 

658 Once the type is made, it's immediately usable:: 

659 

660 table = Table('foo', meta, 

661 Column('id', Integer, primary_key=True), 

662 Column('data', MyType(16)) 

663 ) 

664 

665 The ``get_col_spec()`` method will in most cases receive a keyword 

666 argument ``type_expression`` which refers to the owning expression 

667 of the type as being compiled, such as a :class:`_schema.Column` or 

668 :func:`.cast` construct. This keyword is only sent if the method 

669 accepts keyword arguments (e.g. ``**kw``) in its argument signature; 

670 introspection is used to check for this in order to support legacy 

671 forms of this function. 

672 

673 .. versionadded:: 1.0.0 the owning expression is passed to 

674 the ``get_col_spec()`` method via the keyword argument 

675 ``type_expression``, if it receives ``**kw`` in its signature. 

676 

677 """ 

678 

679 __visit_name__ = "user_defined" 

680 

681 ensure_kwarg = "get_col_spec" 

682 

683 class Comparator(TypeEngine.Comparator): 

684 __slots__ = () 

685 

686 def _adapt_expression(self, op, other_comparator): 

687 if hasattr(self.type, "adapt_operator"): 

688 util.warn_deprecated( 

689 "UserDefinedType.adapt_operator is deprecated. Create " 

690 "a UserDefinedType.Comparator subclass instead which " 

691 "generates the desired expression constructs, given a " 

692 "particular operator." 

693 ) 

694 return self.type.adapt_operator(op), self.type 

695 else: 

696 return super( 

697 UserDefinedType.Comparator, self 

698 )._adapt_expression(op, other_comparator) 

699 

700 comparator_factory = Comparator 

701 

702 def coerce_compared_value(self, op, value): 

703 """Suggest a type for a 'coerced' Python value in an expression. 

704 

705 Default behavior for :class:`.UserDefinedType` is the 

706 same as that of :class:`.TypeDecorator`; by default it returns 

707 ``self``, assuming the compared value should be coerced into 

708 the same type as this one. See 

709 :meth:`.TypeDecorator.coerce_compared_value` for more detail. 

710 

711 """ 

712 

713 return self 

714 

715 

716class Emulated(object): 

717 """Mixin for base types that emulate the behavior of a DB-native type. 

718 

719 An :class:`.Emulated` type will use an available database type 

720 in conjunction with Python-side routines and/or database constraints 

721 in order to approximate the behavior of a database type that is provided 

722 natively by some backends. When a native-providing backend is in 

723 use, the native version of the type is used. This native version 

724 should include the :class:`.NativeForEmulated` mixin to allow it to be 

725 distinguished from :class:`.Emulated`. 

726 

727 Current examples of :class:`.Emulated` are: :class:`.Interval`, 

728 :class:`.Enum`, :class:`.Boolean`. 

729 

730 .. versionadded:: 1.2.0b3 

731 

732 """ 

733 

734 def adapt_to_emulated(self, impltype, **kw): 

735 """Given an impl class, adapt this type to the impl assuming "emulated". 

736 

737 The impl should also be an "emulated" version of this type, 

738 most likely the same class as this type itself. 

739 

740 e.g.: sqltypes.Enum adapts to the Enum class. 

741 

742 """ 

743 return super(Emulated, self).adapt(impltype, **kw) 

744 

745 def adapt(self, impltype, **kw): 

746 if hasattr(impltype, "adapt_emulated_to_native"): 

747 

748 if self.native: 

749 # native support requested, dialect gave us a native 

750 # implementor, pass control over to it 

751 return impltype.adapt_emulated_to_native(self, **kw) 

752 else: 

753 # impltype adapts to native, and we are not native, 

754 # so reject the impltype in favor of "us" 

755 impltype = self.__class__ 

756 

757 if issubclass(impltype, self.__class__): 

758 return self.adapt_to_emulated(impltype, **kw) 

759 else: 

760 return super(Emulated, self).adapt(impltype, **kw) 

761 

762 

763class NativeForEmulated(object): 

764 """Indicates DB-native types supported by an :class:`.Emulated` type. 

765 

766 .. versionadded:: 1.2.0b3 

767 

768 """ 

769 

770 @classmethod 

771 def adapt_emulated_to_native(cls, impl, **kw): 

772 """Given an impl, adapt this type's class to the impl assuming "native". 

773 

774 The impl will be an :class:`.Emulated` class but not a 

775 :class:`.NativeForEmulated`. 

776 

777 e.g.: postgresql.ENUM produces a type given an Enum instance. 

778 

779 """ 

780 return cls(**kw) 

781 

782 

783class TypeDecorator(SchemaEventTarget, TypeEngine): 

784 """Allows the creation of types which add additional functionality 

785 to an existing type. 

786 

787 This method is preferred to direct subclassing of SQLAlchemy's 

788 built-in types as it ensures that all required functionality of 

789 the underlying type is kept in place. 

790 

791 Typical usage:: 

792 

793 import sqlalchemy.types as types 

794 

795 class MyType(types.TypeDecorator): 

796 '''Prefixes Unicode values with "PREFIX:" on the way in and 

797 strips it off on the way out. 

798 ''' 

799 

800 impl = types.Unicode 

801 

802 def process_bind_param(self, value, dialect): 

803 return "PREFIX:" + value 

804 

805 def process_result_value(self, value, dialect): 

806 return value[7:] 

807 

808 def copy(self, **kw): 

809 return MyType(self.impl.length) 

810 

811 The class-level "impl" attribute is required, and can reference any 

812 TypeEngine class. Alternatively, the load_dialect_impl() method 

813 can be used to provide different type classes based on the dialect 

814 given; in this case, the "impl" variable can reference 

815 ``TypeEngine`` as a placeholder. 

816 

817 Types that receive a Python type that isn't similar to the ultimate type 

818 used may want to define the :meth:`TypeDecorator.coerce_compared_value` 

819 method. This is used to give the expression system a hint when coercing 

820 Python objects into bind parameters within expressions. Consider this 

821 expression:: 

822 

823 mytable.c.somecol + datetime.date(2009, 5, 15) 

824 

825 Above, if "somecol" is an ``Integer`` variant, it makes sense that 

826 we're doing date arithmetic, where above is usually interpreted 

827 by databases as adding a number of days to the given date. 

828 The expression system does the right thing by not attempting to 

829 coerce the "date()" value into an integer-oriented bind parameter. 

830 

831 However, in the case of ``TypeDecorator``, we are usually changing an 

832 incoming Python type to something new - ``TypeDecorator`` by default will 

833 "coerce" the non-typed side to be the same type as itself. Such as below, 

834 we define an "epoch" type that stores a date value as an integer:: 

835 

836 class MyEpochType(types.TypeDecorator): 

837 impl = types.Integer 

838 

839 epoch = datetime.date(1970, 1, 1) 

840 

841 def process_bind_param(self, value, dialect): 

842 return (value - self.epoch).days 

843 

844 def process_result_value(self, value, dialect): 

845 return self.epoch + timedelta(days=value) 

846 

847 Our expression of ``somecol + date`` with the above type will coerce the 

848 "date" on the right side to also be treated as ``MyEpochType``. 

849 

850 This behavior can be overridden via the 

851 :meth:`~TypeDecorator.coerce_compared_value` method, which returns a type 

852 that should be used for the value of the expression. Below we set it such 

853 that an integer value will be treated as an ``Integer``, and any other 

854 value is assumed to be a date and will be treated as a ``MyEpochType``:: 

855 

856 def coerce_compared_value(self, op, value): 

857 if isinstance(value, int): 

858 return Integer() 

859 else: 

860 return self 

861 

862 .. warning:: 

863 

864 Note that the **behavior of coerce_compared_value is not inherited 

865 by default from that of the base type**. 

866 If the :class:`.TypeDecorator` is augmenting a 

867 type that requires special logic for certain types of operators, 

868 this method **must** be overridden. A key example is when decorating 

869 the :class:`_postgresql.JSON` and :class:`_postgresql.JSONB` types; 

870 the default rules of :meth:`.TypeEngine.coerce_compared_value` should 

871 be used in order to deal with operators like index operations:: 

872 

873 class MyJsonType(TypeDecorator): 

874 impl = postgresql.JSON 

875 

876 def coerce_compared_value(self, op, value): 

877 return self.impl.coerce_compared_value(op, value) 

878 

879 Without the above step, index operations such as ``mycol['foo']`` 

880 will cause the index value ``'foo'`` to be JSON encoded. 

881 

882 """ 

883 

884 __visit_name__ = "type_decorator" 

885 

886 def __init__(self, *args, **kwargs): 

887 """Construct a :class:`.TypeDecorator`. 

888 

889 Arguments sent here are passed to the constructor 

890 of the class assigned to the ``impl`` class level attribute, 

891 assuming the ``impl`` is a callable, and the resulting 

892 object is assigned to the ``self.impl`` instance attribute 

893 (thus overriding the class attribute of the same name). 

894 

895 If the class level ``impl`` is not a callable (the unusual case), 

896 it will be assigned to the same instance attribute 'as-is', 

897 ignoring those arguments passed to the constructor. 

898 

899 Subclasses can override this to customize the generation 

900 of ``self.impl`` entirely. 

901 

902 """ 

903 

904 if not hasattr(self.__class__, "impl"): 

905 raise AssertionError( 

906 "TypeDecorator implementations " 

907 "require a class-level variable " 

908 "'impl' which refers to the class of " 

909 "type being decorated" 

910 ) 

911 self.impl = to_instance(self.__class__.impl, *args, **kwargs) 

912 

913 coerce_to_is_types = (util.NoneType,) 

914 """Specify those Python types which should be coerced at the expression 

915 level to "IS <constant>" when compared using ``==`` (and same for 

916 ``IS NOT`` in conjunction with ``!=``. 

917 

918 For most SQLAlchemy types, this includes ``NoneType``, as well as 

919 ``bool``. 

920 

921 :class:`.TypeDecorator` modifies this list to only include ``NoneType``, 

922 as typedecorator implementations that deal with boolean types are common. 

923 

924 Custom :class:`.TypeDecorator` classes can override this attribute to 

925 return an empty tuple, in which case no values will be coerced to 

926 constants. 

927 

928 """ 

929 

930 class Comparator(TypeEngine.Comparator): 

931 """A :class:`.TypeEngine.Comparator` that is specific to 

932 :class:`.TypeDecorator`. 

933 

934 User-defined :class:`.TypeDecorator` classes should not typically 

935 need to modify this. 

936 

937 

938 """ 

939 

940 __slots__ = () 

941 

942 def operate(self, op, *other, **kwargs): 

943 kwargs["_python_is_types"] = self.expr.type.coerce_to_is_types 

944 return super(TypeDecorator.Comparator, self).operate( 

945 op, *other, **kwargs 

946 ) 

947 

948 def reverse_operate(self, op, other, **kwargs): 

949 kwargs["_python_is_types"] = self.expr.type.coerce_to_is_types 

950 return super(TypeDecorator.Comparator, self).reverse_operate( 

951 op, other, **kwargs 

952 ) 

953 

954 @property 

955 def comparator_factory(self): 

956 if TypeDecorator.Comparator in self.impl.comparator_factory.__mro__: 

957 return self.impl.comparator_factory 

958 else: 

959 return type( 

960 "TDComparator", 

961 (TypeDecorator.Comparator, self.impl.comparator_factory), 

962 {}, 

963 ) 

964 

965 def _gen_dialect_impl(self, dialect): 

966 """ 

967 #todo 

968 """ 

969 adapted = dialect.type_descriptor(self) 

970 if adapted is not self: 

971 return adapted 

972 

973 # otherwise adapt the impl type, link 

974 # to a copy of this TypeDecorator and return 

975 # that. 

976 typedesc = self._unwrapped_dialect_impl(dialect) 

977 tt = self.copy() 

978 if not isinstance(tt, self.__class__): 

979 raise AssertionError( 

980 "Type object %s does not properly " 

981 "implement the copy() method, it must " 

982 "return an object of type %s" % (self, self.__class__) 

983 ) 

984 tt.impl = typedesc 

985 return tt 

986 

987 @property 

988 def _type_affinity(self): 

989 """ 

990 #todo 

991 """ 

992 return self.impl._type_affinity 

993 

994 def _set_parent(self, column): 

995 """Support SchemaEventTarget""" 

996 

997 super(TypeDecorator, self)._set_parent(column) 

998 

999 if isinstance(self.impl, SchemaEventTarget): 

1000 self.impl._set_parent(column) 

1001 

1002 def _set_parent_with_dispatch(self, parent): 

1003 """Support SchemaEventTarget""" 

1004 

1005 super(TypeDecorator, self)._set_parent_with_dispatch(parent) 

1006 

1007 if isinstance(self.impl, SchemaEventTarget): 

1008 self.impl._set_parent_with_dispatch(parent) 

1009 

1010 def type_engine(self, dialect): 

1011 """Return a dialect-specific :class:`.TypeEngine` instance 

1012 for this :class:`.TypeDecorator`. 

1013 

1014 In most cases this returns a dialect-adapted form of 

1015 the :class:`.TypeEngine` type represented by ``self.impl``. 

1016 Makes usage of :meth:`dialect_impl` but also traverses 

1017 into wrapped :class:`.TypeDecorator` instances. 

1018 Behavior can be customized here by overriding 

1019 :meth:`load_dialect_impl`. 

1020 

1021 """ 

1022 adapted = dialect.type_descriptor(self) 

1023 if not isinstance(adapted, type(self)): 

1024 return adapted 

1025 elif isinstance(self.impl, TypeDecorator): 

1026 return self.impl.type_engine(dialect) 

1027 else: 

1028 return self.load_dialect_impl(dialect) 

1029 

1030 def load_dialect_impl(self, dialect): 

1031 """Return a :class:`.TypeEngine` object corresponding to a dialect. 

1032 

1033 This is an end-user override hook that can be used to provide 

1034 differing types depending on the given dialect. It is used 

1035 by the :class:`.TypeDecorator` implementation of :meth:`type_engine` 

1036 to help determine what type should ultimately be returned 

1037 for a given :class:`.TypeDecorator`. 

1038 

1039 By default returns ``self.impl``. 

1040 

1041 """ 

1042 return self.impl 

1043 

1044 def _unwrapped_dialect_impl(self, dialect): 

1045 """Return the 'unwrapped' dialect impl for this type. 

1046 

1047 For a type that applies wrapping logic (e.g. TypeDecorator), give 

1048 us the real, actual dialect-level type that is used. 

1049 

1050 This is used by TypeDecorator itself as well at least one case where 

1051 dialects need to check that a particular specific dialect-level 

1052 type is in use, within the :meth:`.DefaultDialect.set_input_sizes` 

1053 method. 

1054 

1055 """ 

1056 return self.load_dialect_impl(dialect).dialect_impl(dialect) 

1057 

1058 def __getattr__(self, key): 

1059 """Proxy all other undefined accessors to the underlying 

1060 implementation.""" 

1061 return getattr(self.impl, key) 

1062 

1063 def process_literal_param(self, value, dialect): 

1064 """Receive a literal parameter value to be rendered inline within 

1065 a statement. 

1066 

1067 This method is used when the compiler renders a 

1068 literal value without using binds, typically within DDL 

1069 such as in the "server default" of a column or an expression 

1070 within a CHECK constraint. 

1071 

1072 The returned string will be rendered into the output string. 

1073 

1074 .. versionadded:: 0.9.0 

1075 

1076 """ 

1077 raise NotImplementedError() 

1078 

1079 def process_bind_param(self, value, dialect): 

1080 """Receive a bound parameter value to be converted. 

1081 

1082 Subclasses override this method to return the 

1083 value that should be passed along to the underlying 

1084 :class:`.TypeEngine` object, and from there to the 

1085 DBAPI ``execute()`` method. 

1086 

1087 The operation could be anything desired to perform custom 

1088 behavior, such as transforming or serializing data. 

1089 This could also be used as a hook for validating logic. 

1090 

1091 This operation should be designed with the reverse operation 

1092 in mind, which would be the process_result_value method of 

1093 this class. 

1094 

1095 :param value: Data to operate upon, of any type expected by 

1096 this method in the subclass. Can be ``None``. 

1097 :param dialect: the :class:`.Dialect` in use. 

1098 

1099 """ 

1100 

1101 raise NotImplementedError() 

1102 

1103 def process_result_value(self, value, dialect): 

1104 """Receive a result-row column value to be converted. 

1105 

1106 Subclasses should implement this method to operate on data 

1107 fetched from the database. 

1108 

1109 Subclasses override this method to return the 

1110 value that should be passed back to the application, 

1111 given a value that is already processed by 

1112 the underlying :class:`.TypeEngine` object, originally 

1113 from the DBAPI cursor method ``fetchone()`` or similar. 

1114 

1115 The operation could be anything desired to perform custom 

1116 behavior, such as transforming or serializing data. 

1117 This could also be used as a hook for validating logic. 

1118 

1119 :param value: Data to operate upon, of any type expected by 

1120 this method in the subclass. Can be ``None``. 

1121 :param dialect: the :class:`.Dialect` in use. 

1122 

1123 This operation should be designed to be reversible by 

1124 the "process_bind_param" method of this class. 

1125 

1126 """ 

1127 

1128 raise NotImplementedError() 

1129 

1130 @util.memoized_property 

1131 def _has_bind_processor(self): 

1132 """memoized boolean, check if process_bind_param is implemented. 

1133 

1134 Allows the base process_bind_param to raise 

1135 NotImplementedError without needing to test an expensive 

1136 exception throw. 

1137 

1138 """ 

1139 

1140 return ( 

1141 self.__class__.process_bind_param.__code__ 

1142 is not TypeDecorator.process_bind_param.__code__ 

1143 ) 

1144 

1145 @util.memoized_property 

1146 def _has_literal_processor(self): 

1147 """memoized boolean, check if process_literal_param is implemented. 

1148 

1149 

1150 """ 

1151 

1152 return ( 

1153 self.__class__.process_literal_param.__code__ 

1154 is not TypeDecorator.process_literal_param.__code__ 

1155 ) 

1156 

1157 def literal_processor(self, dialect): 

1158 """Provide a literal processing function for the given 

1159 :class:`.Dialect`. 

1160 

1161 Subclasses here will typically override 

1162 :meth:`.TypeDecorator.process_literal_param` instead of this method 

1163 directly. 

1164 

1165 By default, this method makes use of 

1166 :meth:`.TypeDecorator.process_bind_param` if that method is 

1167 implemented, where :meth:`.TypeDecorator.process_literal_param` is 

1168 not. The rationale here is that :class:`.TypeDecorator` typically 

1169 deals with Python conversions of data that are above the layer of 

1170 database presentation. With the value converted by 

1171 :meth:`.TypeDecorator.process_bind_param`, the underlying type will 

1172 then handle whether it needs to be presented to the DBAPI as a bound 

1173 parameter or to the database as an inline SQL value. 

1174 

1175 .. versionadded:: 0.9.0 

1176 

1177 """ 

1178 if self._has_literal_processor: 

1179 process_param = self.process_literal_param 

1180 elif self._has_bind_processor: 

1181 # the bind processor should normally be OK 

1182 # for TypeDecorator since it isn't doing DB-level 

1183 # handling, the handling here won't be different for bound vs. 

1184 # literals. 

1185 process_param = self.process_bind_param 

1186 else: 

1187 process_param = None 

1188 

1189 if process_param: 

1190 impl_processor = self.impl.literal_processor(dialect) 

1191 if impl_processor: 

1192 

1193 def process(value): 

1194 return impl_processor(process_param(value, dialect)) 

1195 

1196 else: 

1197 

1198 def process(value): 

1199 return process_param(value, dialect) 

1200 

1201 return process 

1202 else: 

1203 return self.impl.literal_processor(dialect) 

1204 

1205 def bind_processor(self, dialect): 

1206 """Provide a bound value processing function for the 

1207 given :class:`.Dialect`. 

1208 

1209 This is the method that fulfills the :class:`.TypeEngine` 

1210 contract for bound value conversion. :class:`.TypeDecorator` 

1211 will wrap a user-defined implementation of 

1212 :meth:`process_bind_param` here. 

1213 

1214 User-defined code can override this method directly, 

1215 though its likely best to use :meth:`process_bind_param` so that 

1216 the processing provided by ``self.impl`` is maintained. 

1217 

1218 :param dialect: Dialect instance in use. 

1219 

1220 This method is the reverse counterpart to the 

1221 :meth:`result_processor` method of this class. 

1222 

1223 """ 

1224 if self._has_bind_processor: 

1225 process_param = self.process_bind_param 

1226 impl_processor = self.impl.bind_processor(dialect) 

1227 if impl_processor: 

1228 

1229 def process(value): 

1230 return impl_processor(process_param(value, dialect)) 

1231 

1232 else: 

1233 

1234 def process(value): 

1235 return process_param(value, dialect) 

1236 

1237 return process 

1238 else: 

1239 return self.impl.bind_processor(dialect) 

1240 

1241 @util.memoized_property 

1242 def _has_result_processor(self): 

1243 """memoized boolean, check if process_result_value is implemented. 

1244 

1245 Allows the base process_result_value to raise 

1246 NotImplementedError without needing to test an expensive 

1247 exception throw. 

1248 

1249 """ 

1250 return ( 

1251 self.__class__.process_result_value.__code__ 

1252 is not TypeDecorator.process_result_value.__code__ 

1253 ) 

1254 

1255 def result_processor(self, dialect, coltype): 

1256 """Provide a result value processing function for the given 

1257 :class:`.Dialect`. 

1258 

1259 This is the method that fulfills the :class:`.TypeEngine` 

1260 contract for result value conversion. :class:`.TypeDecorator` 

1261 will wrap a user-defined implementation of 

1262 :meth:`process_result_value` here. 

1263 

1264 User-defined code can override this method directly, 

1265 though its likely best to use :meth:`process_result_value` so that 

1266 the processing provided by ``self.impl`` is maintained. 

1267 

1268 :param dialect: Dialect instance in use. 

1269 :param coltype: A SQLAlchemy data type 

1270 

1271 This method is the reverse counterpart to the 

1272 :meth:`bind_processor` method of this class. 

1273 

1274 """ 

1275 if self._has_result_processor: 

1276 process_value = self.process_result_value 

1277 impl_processor = self.impl.result_processor(dialect, coltype) 

1278 if impl_processor: 

1279 

1280 def process(value): 

1281 return process_value(impl_processor(value), dialect) 

1282 

1283 else: 

1284 

1285 def process(value): 

1286 return process_value(value, dialect) 

1287 

1288 return process 

1289 else: 

1290 return self.impl.result_processor(dialect, coltype) 

1291 

1292 @util.memoized_property 

1293 def _has_bind_expression(self): 

1294 return ( 

1295 self.__class__.bind_expression.__code__ 

1296 is not TypeDecorator.bind_expression.__code__ 

1297 ) or self.impl._has_bind_expression 

1298 

1299 def bind_expression(self, bindparam): 

1300 return self.impl.bind_expression(bindparam) 

1301 

1302 @util.memoized_property 

1303 def _has_column_expression(self): 

1304 """memoized boolean, check if column_expression is implemented. 

1305 

1306 Allows the method to be skipped for the vast majority of expression 

1307 types that don't use this feature. 

1308 

1309 """ 

1310 

1311 return ( 

1312 self.__class__.column_expression.__code__ 

1313 is not TypeDecorator.column_expression.__code__ 

1314 ) or self.impl._has_column_expression 

1315 

1316 def column_expression(self, column): 

1317 return self.impl.column_expression(column) 

1318 

1319 def coerce_compared_value(self, op, value): 

1320 """Suggest a type for a 'coerced' Python value in an expression. 

1321 

1322 By default, returns self. This method is called by 

1323 the expression system when an object using this type is 

1324 on the left or right side of an expression against a plain Python 

1325 object which does not yet have a SQLAlchemy type assigned:: 

1326 

1327 expr = table.c.somecolumn + 35 

1328 

1329 Where above, if ``somecolumn`` uses this type, this method will 

1330 be called with the value ``operator.add`` 

1331 and ``35``. The return value is whatever SQLAlchemy type should 

1332 be used for ``35`` for this particular operation. 

1333 

1334 """ 

1335 return self 

1336 

1337 def copy(self, **kw): 

1338 """Produce a copy of this :class:`.TypeDecorator` instance. 

1339 

1340 This is a shallow copy and is provided to fulfill part of 

1341 the :class:`.TypeEngine` contract. It usually does not 

1342 need to be overridden unless the user-defined :class:`.TypeDecorator` 

1343 has local state that should be deep-copied. 

1344 

1345 """ 

1346 

1347 instance = self.__class__.__new__(self.__class__) 

1348 instance.__dict__.update(self.__dict__) 

1349 return instance 

1350 

1351 def get_dbapi_type(self, dbapi): 

1352 """Return the DBAPI type object represented by this 

1353 :class:`.TypeDecorator`. 

1354 

1355 By default this calls upon :meth:`.TypeEngine.get_dbapi_type` of the 

1356 underlying "impl". 

1357 """ 

1358 return self.impl.get_dbapi_type(dbapi) 

1359 

1360 def compare_values(self, x, y): 

1361 """Given two values, compare them for equality. 

1362 

1363 By default this calls upon :meth:`.TypeEngine.compare_values` 

1364 of the underlying "impl", which in turn usually 

1365 uses the Python equals operator ``==``. 

1366 

1367 This function is used by the ORM to compare 

1368 an original-loaded value with an intercepted 

1369 "changed" value, to determine if a net change 

1370 has occurred. 

1371 

1372 """ 

1373 return self.impl.compare_values(x, y) 

1374 

1375 @property 

1376 def sort_key_function(self): 

1377 return self.impl.sort_key_function 

1378 

1379 def __repr__(self): 

1380 return util.generic_repr(self, to_inspect=self.impl) 

1381 

1382 

1383class Variant(TypeDecorator): 

1384 """A wrapping type that selects among a variety of 

1385 implementations based on dialect in use. 

1386 

1387 The :class:`.Variant` type is typically constructed 

1388 using the :meth:`.TypeEngine.with_variant` method. 

1389 

1390 .. seealso:: :meth:`.TypeEngine.with_variant` for an example of use. 

1391 

1392 """ 

1393 

1394 def __init__(self, base, mapping): 

1395 """Construct a new :class:`.Variant`. 

1396 

1397 :param base: the base 'fallback' type 

1398 :param mapping: dictionary of string dialect names to 

1399 :class:`.TypeEngine` instances. 

1400 

1401 """ 

1402 self.impl = base 

1403 self.mapping = mapping 

1404 

1405 def coerce_compared_value(self, operator, value): 

1406 result = self.impl.coerce_compared_value(operator, value) 

1407 if result is self.impl: 

1408 return self 

1409 else: 

1410 return result 

1411 

1412 def load_dialect_impl(self, dialect): 

1413 if dialect.name in self.mapping: 

1414 return self.mapping[dialect.name] 

1415 else: 

1416 return self.impl 

1417 

1418 def _set_parent(self, column): 

1419 """Support SchemaEventTarget""" 

1420 

1421 if isinstance(self.impl, SchemaEventTarget): 

1422 self.impl._set_parent(column) 

1423 for impl in self.mapping.values(): 

1424 if isinstance(impl, SchemaEventTarget): 

1425 impl._set_parent(column) 

1426 

1427 def _set_parent_with_dispatch(self, parent): 

1428 """Support SchemaEventTarget""" 

1429 

1430 if isinstance(self.impl, SchemaEventTarget): 

1431 self.impl._set_parent_with_dispatch(parent) 

1432 for impl in self.mapping.values(): 

1433 if isinstance(impl, SchemaEventTarget): 

1434 impl._set_parent_with_dispatch(parent) 

1435 

1436 def with_variant(self, type_, dialect_name): 

1437 r"""Return a new :class:`.Variant` which adds the given 

1438 type + dialect name to the mapping, in addition to the 

1439 mapping present in this :class:`.Variant`. 

1440 

1441 :param type\_: a :class:`.TypeEngine` that will be selected 

1442 as a variant from the originating type, when a dialect 

1443 of the given name is in use. 

1444 :param dialect_name: base name of the dialect which uses 

1445 this type. (i.e. ``'postgresql'``, ``'mysql'``, etc.) 

1446 

1447 """ 

1448 

1449 if dialect_name in self.mapping: 

1450 raise exc.ArgumentError( 

1451 "Dialect '%s' is already present in " 

1452 "the mapping for this Variant" % dialect_name 

1453 ) 

1454 mapping = self.mapping.copy() 

1455 mapping[dialect_name] = type_ 

1456 return Variant(self.impl, mapping) 

1457 

1458 @property 

1459 def comparator_factory(self): 

1460 """express comparison behavior in terms of the base type""" 

1461 return self.impl.comparator_factory 

1462 

1463 

1464def _reconstitute_comparator(expression): 

1465 return expression.comparator 

1466 

1467 

1468def to_instance(typeobj, *arg, **kw): 

1469 if typeobj is None: 

1470 return NULLTYPE 

1471 

1472 if util.callable(typeobj): 

1473 return typeobj(*arg, **kw) 

1474 else: 

1475 return typeobj 

1476 

1477 

1478def adapt_type(typeobj, colspecs): 

1479 if isinstance(typeobj, type): 

1480 typeobj = typeobj() 

1481 for t in typeobj.__class__.__mro__[0:-1]: 

1482 try: 

1483 impltype = colspecs[t] 

1484 break 

1485 except KeyError: 

1486 pass 

1487 else: 

1488 # couldn't adapt - so just return the type itself 

1489 # (it may be a user-defined type) 

1490 return typeobj 

1491 # if we adapted the given generic type to a database-specific type, 

1492 # but it turns out the originally given "generic" type 

1493 # is actually a subclass of our resulting type, then we were already 

1494 # given a more specific type than that required; so use that. 

1495 if issubclass(typeobj.__class__, impltype): 

1496 return typeobj 

1497 return typeobj.adapt(impltype)