You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.5KB

  1. # engine/mock.py
  2. # Copyright (C) 2005-2021 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. from operator import attrgetter
  8. from . import base
  9. from . import url as _url
  10. from .. import util
  11. from ..sql import ddl
  12. class MockConnection(base.Connectable):
  13. def __init__(self, dialect, execute):
  14. self._dialect = dialect
  15. self.execute = execute
  16. engine = property(lambda s: s)
  17. dialect = property(attrgetter("_dialect"))
  18. name = property(lambda s: s._dialect.name)
  19. def schema_for_object(self, obj):
  20. return obj.schema
  21. def connect(self, **kwargs):
  22. return self
  23. def execution_options(self, **kw):
  24. return self
  25. def compiler(self, statement, parameters, **kwargs):
  26. return self._dialect.compiler(
  27. statement, parameters, engine=self, **kwargs
  28. )
  29. def create(self, entity, **kwargs):
  30. kwargs["checkfirst"] = False
  31. ddl.SchemaGenerator(self.dialect, self, **kwargs).traverse_single(
  32. entity
  33. )
  34. def drop(self, entity, **kwargs):
  35. kwargs["checkfirst"] = False
  36. ddl.SchemaDropper(self.dialect, self, **kwargs).traverse_single(entity)
  37. def _run_ddl_visitor(
  38. self, visitorcallable, element, connection=None, **kwargs
  39. ):
  40. kwargs["checkfirst"] = False
  41. visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  42. def execute(self, object_, *multiparams, **params):
  43. raise NotImplementedError()
  44. def create_mock_engine(url, executor, **kw):
  45. """Create a "mock" engine used for echoing DDL.
  46. This is a utility function used for debugging or storing the output of DDL
  47. sequences as generated by :meth:`_schema.MetaData.create_all`
  48. and related methods.
  49. The function accepts a URL which is used only to determine the kind of
  50. dialect to be used, as well as an "executor" callable function which
  51. will receive a SQL expression object and parameters, which can then be
  52. echoed or otherwise printed. The executor's return value is not handled,
  53. nor does the engine allow regular string statements to be invoked, and
  54. is therefore only useful for DDL that is sent to the database without
  55. receiving any results.
  56. E.g.::
  57. from sqlalchemy import create_mock_engine
  58. def dump(sql, *multiparams, **params):
  59. print(sql.compile(dialect=engine.dialect))
  60. engine = create_mock_engine('postgresql://', dump)
  61. metadata.create_all(engine, checkfirst=False)
  62. :param url: A string URL which typically needs to contain only the
  63. database backend name.
  64. :param executor: a callable which receives the arguments ``sql``,
  65. ``*multiparams`` and ``**params``. The ``sql`` parameter is typically
  66. an instance of :class:`.DDLElement`, which can then be compiled into a
  67. string using :meth:`.DDLElement.compile`.
  68. .. versionadded:: 1.4 - the :func:`.create_mock_engine` function replaces
  69. the previous "mock" engine strategy used with
  70. :func:`_sa.create_engine`.
  71. .. seealso::
  72. :ref:`faq_ddl_as_string`
  73. """
  74. # create url.URL object
  75. u = _url.make_url(url)
  76. dialect_cls = u.get_dialect()
  77. dialect_args = {}
  78. # consume dialect arguments from kwargs
  79. for k in util.get_cls_kwargs(dialect_cls):
  80. if k in kw:
  81. dialect_args[k] = kw.pop(k)
  82. # create dialect
  83. dialect = dialect_cls(**dialect_args)
  84. return MockConnection(dialect, executor)