def _has_sqlite(self): from sqlalchemy_1_3 import create_engine try: create_engine("sqlite://") return True except ImportError: return False
def test_reset_on_return(self): dbapi = MockDBAPI( foober=12, lala=18, hoho={"this": "dict"}, fooz="somevalue" ) for (value, expected) in [ ("rollback", pool.reset_rollback), ("commit", pool.reset_commit), (None, pool.reset_none), (True, pool.reset_rollback), (False, pool.reset_none), ]: e = create_engine( "postgresql://", pool_reset_on_return=value, module=dbapi, _initialize=False, ) assert e.pool._reset_on_return is expected assert_raises( exc.ArgumentError, create_engine, "postgresql://", pool_reset_on_return="hi", module=dbapi, _initialize=False, )
def test_ddl_execute(self): engine = create_engine("sqlite:///") cx = engine.connect() table = self.users ddl = DDL("SELECT 1") for spec in ( (engine.execute, ddl), (engine.execute, ddl, table), (cx.execute, ddl), (cx.execute, ddl, table), (ddl.execute, engine), (ddl.execute, engine, table), (ddl.execute, cx), (ddl.execute, cx, table), ): fn = spec[0] arg = spec[1:] r = fn(*arg) eq_(list(r), [(1, )]) for fn, kw in ((ddl.execute, {}), (ddl.execute, dict(target=table))): assert_raises(tsa.exc.UnboundExecutionError, fn, **kw) for bind in engine, cx: ddl.bind = bind for fn, kw in ( (ddl.execute, {}), (ddl.execute, dict(target=table)), ): r = fn(**kw) eq_(list(r), [(1, )])
def test_dialect_initialize_retry_if_exception(self): from sqlalchemy_1_3.engine.url import URL from sqlalchemy_1_3.engine.default import DefaultDialect dbapi = self.dbapi class MyURL(URL): def _get_entrypoint(self): return Dialect def get_dialect(self): return Dialect class Dialect(DefaultDialect): initialize = Mock() # note that the first_connect hook is only invoked when the pool # makes a new DBAPI connection, and not when it checks out an existing # connection. So there is a dependency here that if the initializer # raises an exception, the pool-level connection attempt is also # failed, meaning no DBAPI connection is pooled. If the first_connect # exception raise did not prevent the connection from being pooled, # there could be the case where the pool could return that connection # on a subsequent attempt without initialization having proceeded. Dialect.initialize.side_effect = TypeError engine = create_engine(MyURL("foo://"), module=dbapi) assert_raises(TypeError, engine.connect) eq_(Dialect.initialize.call_count, 1) is_true(engine.pool._pool.empty()) assert_raises(TypeError, engine.connect) eq_(Dialect.initialize.call_count, 2) is_true(engine.pool._pool.empty()) engine.dispose() assert_raises(TypeError, engine.connect) eq_(Dialect.initialize.call_count, 3) is_true(engine.pool._pool.empty()) Dialect.initialize.side_effect = None conn = engine.connect() eq_(Dialect.initialize.call_count, 4) conn.close() is_false(engine.pool._pool.empty()) conn = engine.connect() eq_(Dialect.initialize.call_count, 4) conn.close() is_false(engine.pool._pool.empty()) engine.dispose() conn = engine.connect() eq_(Dialect.initialize.call_count, 4) conn.close() is_false(engine.pool._pool.empty())
def test_dialect_initialize_once(self): from sqlalchemy_1_3.engine.url import URL from sqlalchemy_1_3.engine.default import DefaultDialect dbapi = self.dbapi class MyURL(URL): def _get_entrypoint(self): return Dialect def get_dialect(self): return Dialect class Dialect(DefaultDialect): initialize = Mock() engine = create_engine(MyURL("foo://"), module=dbapi) engine.connect() # note that the dispose() call replaces the old pool with a new one; # this is to test that even though a single pool is using # dispatch.exec_once(), by replacing the pool with a new one, the event # would normally fire again onless once=True is set on the original # listen as well. engine.dispose() engine.connect() eq_(Dialect.initialize.call_count, 1)
def test_wrapper_hooks(self): def get_dialect_cls(url): url.drivername = "sqlite" return url.get_dialect() global WrapperFactory WrapperFactory = Mock() WrapperFactory.get_dialect_cls.side_effect = get_dialect_cls registry.register("wrapperdialect", __name__, "WrapperFactory") from sqlalchemy_1_3.dialects import sqlite e = create_engine("wrapperdialect://") eq_(e.dialect.name, "sqlite") assert isinstance(e.dialect, sqlite.dialect) eq_( WrapperFactory.mock_calls, [ call.get_dialect_cls(url.make_url("sqlite://")), call.engine_created(e), ], )
def test_cx_oracle_service_name(self): url_string = "oracle+cx_oracle://scott:tiger@host/?service_name=hr" eng = create_engine(url_string, _initialize=False) cargs, cparams = eng.dialect.create_connect_args(eng.url) assert "SERVICE_NAME=hr" in cparams["dsn"] assert "SID=hr" not in cparams["dsn"]
def test_recycle(self): dbapi = MockDBAPI( foober=12, lala=18, hoho={"this": "dict"}, fooz="somevalue" ) e = create_engine( "postgresql://", pool_recycle=472, module=dbapi, _initialize=False ) assert e.pool._recycle == 472
def test_urlattr(self): """test the url attribute on ``Engine``.""" e = create_engine( "mysql://*****:*****@localhost/test", module=mock_dbapi, _initialize=False, ) u = url.make_url("mysql://*****:*****@localhost/test") e2 = create_engine(u, module=mock_dbapi, _initialize=False) assert e.url.drivername == e2.url.drivername == "mysql" assert e.url.username == e2.url.username == "scott" assert e2.url is u assert str(u) == "mysql://*****:*****@localhost/test" assert repr(u) == "mysql://*****:*****@localhost/test" assert repr(e) == "Engine(mysql://scott:***@localhost/test)" assert repr(e2) == "Engine(mysql://scott:***@localhost/test)"
def test_connect_query(self): dbapi = MockDBAPI(foober="12", lala="18", fooz="somevalue") e = create_engine( "postgresql://*****:*****@somehost/test?foobe" "r=12&lala=18&fooz=somevalue", module=dbapi, _initialize=False, ) e.connect()
def test_per_option_engine(self): eng = create_engine(testing.db.url).execution_options( isolation_level=self._non_default_isolation_level() ) conn = eng.connect() eq_( eng.dialect.get_isolation_level(conn.connection), self._non_default_isolation_level(), )
def test_isolation_level_accessors_connection_option_modified(self): eng = create_engine(testing.db.url) with eng.connect() as conn: c2 = conn.execution_options( isolation_level=self._non_default_isolation_level() ) eq_(conn.default_isolation_level, self._default_isolation_level()) eq_( conn.get_isolation_level(), self._non_default_isolation_level() ) eq_(c2.get_isolation_level(), self._non_default_isolation_level())
def test_kwargs(self): dbapi = MockDBAPI( foober=12, lala=18, hoho={"this": "dict"}, fooz="somevalue" ) e = create_engine( "postgresql://*****:*****@somehost/test?fooz=" "somevalue", connect_args={"foober": 12, "lala": 18, "hoho": {"this": "dict"}}, module=dbapi, _initialize=False, ) e.connect()
def test_minimal_engine_execute(self, variance=0.10): # create an engine without any instrumentation. e = create_engine("sqlite://") # ensure initial connect activities complete e.execute("select 1") @profiling.function_call_count() def go(): e.execute("select 1") go()
def test_register_legacy(self): tokens = __name__.split(".") global dialect dialect = MockDialect registry.register( "mockdialect.foob", ".".join(tokens[0:-1]), tokens[-1] ) e = create_engine("mockdialect+foob://") assert isinstance(e.dialect, MockDialect)
def test_plugin_multiple_url_registration(self): from sqlalchemy_1_3.dialects import sqlite global MyEnginePlugin1 global MyEnginePlugin2 def side_effect_1(url, kw): eq_(kw, {"logging_name": "foob"}) kw["logging_name"] = "bar" url.query.pop("myplugin1_arg", None) return MyEnginePlugin1 def side_effect_2(url, kw): url.query.pop("myplugin2_arg", None) return MyEnginePlugin2 MyEnginePlugin1 = Mock(side_effect=side_effect_1) MyEnginePlugin2 = Mock(side_effect=side_effect_2) plugins.register("engineplugin1", __name__, "MyEnginePlugin1") plugins.register("engineplugin2", __name__, "MyEnginePlugin2") e = create_engine( "sqlite:///?plugin=engineplugin1&foo=bar&myplugin1_arg=bat" "&plugin=engineplugin2&myplugin2_arg=hoho", logging_name="foob", ) eq_(e.dialect.name, "sqlite") eq_(e.logging_name, "bar") # plugin args are removed from URL. eq_(e.url.query, {"foo": "bar"}) assert isinstance(e.dialect, sqlite.dialect) eq_( MyEnginePlugin1.mock_calls, [ call(url.make_url("sqlite:///?foo=bar"), {}), call.handle_dialect_kwargs(sqlite.dialect, mock.ANY), call.handle_pool_kwargs(mock.ANY, {"dialect": e.dialect}), call.engine_created(e), ], ) eq_( MyEnginePlugin2.mock_calls, [ call(url.make_url("sqlite:///?foo=bar"), {}), call.handle_dialect_kwargs(sqlite.dialect, mock.ANY), call.handle_pool_kwargs(mock.ANY, {"dialect": e.dialect}), call.engine_created(e), ], )
def test_per_engine(self): # new in 0.9 eng = create_engine( testing.db.url, execution_options={ "isolation_level": self._non_default_isolation_level() }, ) conn = eng.connect() eq_( eng.dialect.get_isolation_level(conn.connection), self._non_default_isolation_level(), )
def _chaos(self): e = create_engine("sqlite://") try: self._make_tables(e) for i in range(2): try: self._automap(e) except: self._success = False raise time.sleep(random.random()) finally: e.dispose()
def mock_engine(self): def executor(*a, **kw): return None engine = create_engine(testing.db.name + "://", strategy="mock", executor=executor) # fmt: off engine.dialect.identifier_preparer = \ tsa.sql.compiler.IdentifierPreparer( engine.dialect ) # fmt: on return engine
def test_poolargs(self): """test that connection pool args make it thru""" e = create_engine( "postgresql://", creator=None, pool_recycle=50, echo_pool=None, module=mock_dbapi, _initialize=False, ) assert e.pool._recycle == 50 # these args work for QueuePool e = create_engine( "postgresql://", max_overflow=8, pool_timeout=60, poolclass=tsa.pool.QueuePool, module=mock_dbapi, _initialize=False, ) # but not SingletonThreadPool assert_raises( TypeError, create_engine, "sqlite://", max_overflow=8, pool_timeout=60, poolclass=tsa.pool.SingletonThreadPool, module=mock_sqlite_dbapi, _initialize=False, )
def test_minimal_connection_execute(self): # create an engine without any instrumentation. e = create_engine("sqlite://") c = e.connect() # ensure initial connect activities complete c.execute("select 1") @profiling.function_call_count() def go(): c.execute("select 1") try: go() finally: c.close()
def test_plugin_url_registration(self): from sqlalchemy_1_3.dialects import sqlite global MyEnginePlugin def side_effect(url, kw): eq_( url.query, { "plugin": "engineplugin", "myplugin_arg": "bat", "foo": "bar", }, ) eq_(kw, {"logging_name": "foob"}) kw["logging_name"] = "bar" url.query.pop("myplugin_arg", None) return MyEnginePlugin MyEnginePlugin = Mock(side_effect=side_effect) plugins.register("engineplugin", __name__, "MyEnginePlugin") e = create_engine( "sqlite:///?plugin=engineplugin&foo=bar&myplugin_arg=bat", logging_name="foob", ) eq_(e.dialect.name, "sqlite") eq_(e.logging_name, "bar") # plugin args are removed from URL. eq_(e.url.query, {"foo": "bar"}) assert isinstance(e.dialect, sqlite.dialect) eq_( MyEnginePlugin.mock_calls, [ call(url.make_url("sqlite:///?foo=bar"), {}), call.handle_dialect_kwargs(sqlite.dialect, mock.ANY), call.handle_pool_kwargs(mock.ANY, {"dialect": e.dialect}), call.engine_created(e), ], ) # url was modified in place by MyEnginePlugin eq_(str(MyEnginePlugin.mock_calls[0][1][0]), "sqlite:///?foo=bar")
def test_custom(self): dbapi = MockDBAPI( foober=12, lala=18, hoho={"this": "dict"}, fooz="somevalue" ) def connect(): return dbapi.connect( foober=12, lala=18, fooz="somevalue", hoho={"this": "dict"} ) # start the postgresql dialect, but put our mock DBAPI as the # module instead of psycopg e = create_engine( "postgresql://", creator=connect, module=dbapi, _initialize=False ) e.connect()
def test_plugin_arg_registration(self): from sqlalchemy_1_3.dialects import sqlite global MyEnginePlugin def side_effect(url, kw): eq_( kw, { "logging_name": "foob", "plugins": ["engineplugin"], "myplugin_arg": "bat", }, ) kw["logging_name"] = "bar" kw.pop("myplugin_arg", None) return MyEnginePlugin MyEnginePlugin = Mock(side_effect=side_effect) plugins.register("engineplugin", __name__, "MyEnginePlugin") e = create_engine( "sqlite:///?foo=bar", logging_name="foob", plugins=["engineplugin"], myplugin_arg="bat", ) eq_(e.dialect.name, "sqlite") eq_(e.logging_name, "bar") assert isinstance(e.dialect, sqlite.dialect) eq_( MyEnginePlugin.mock_calls, [ call(url.make_url("sqlite:///?foo=bar"), {}), call.handle_dialect_kwargs(sqlite.dialect, mock.ANY), call.handle_pool_kwargs(mock.ANY, {"dialect": e.dialect}), call.engine_created(e), ], )
def mock_engine(dialect_name=None): """Provides a mocking engine based on the current testing.db. This is normally used to test DDL generation flow as emitted by an Engine. It should not be used in other cases, as assert_compile() and assert_sql_execution() are much better choices with fewer moving parts. """ from sqlalchemy_1_3 import create_engine if not dialect_name: dialect_name = config.db.name buffer = [] def executor(sql, *a, **kw): buffer.append(sql) def assert_sql(stmts): recv = [re.sub(r"[\n\t]", "", str(s)) for s in buffer] assert recv == stmts, recv def print_sql(): d = engine.dialect return "\n".join(str(s.compile(dialect=d)) for s in engine.mock) engine = create_engine(dialect_name + "://", strategy="mock", executor=executor) assert not hasattr(engine, "mock") engine.mock = buffer engine.assert_sql = assert_sql engine.print_sql = print_sql return engine
def testing_engine(url=None, options=None): """Produce an engine configured by --options with optional overrides.""" from sqlalchemy_1_3 import create_engine from sqlalchemy_1_3.engine.url import make_url if not options: use_reaper = True else: use_reaper = options.pop("use_reaper", True) url = url or config.db.url url = make_url(url) if options is None: if config.db is None or url.drivername == config.db.url.drivername: options = config.db_opts else: options = {} elif config.db is not None and url.drivername == config.db.url.drivername: default_opt = config.db_opts.copy() default_opt.update(options) engine = create_engine(url, **options) engine._has_events = True # enable event blocks, helps with profiling if isinstance(engine.pool, pool.QueuePool): engine.pool._timeout = 0 engine.pool._max_overflow = 0 if use_reaper: event.listen(engine.pool, "connect", testing_reaper.connect) event.listen(engine.pool, "checkout", testing_reaper.checkout) event.listen(engine.pool, "invalidate", testing_reaper.invalidate) testing_reaper.add_engine(engine) return engine
def test_isolation_level_accessors_connection_default(self): eng = create_engine(testing.db.url) with eng.connect() as conn: eq_(conn.default_isolation_level, self._default_isolation_level()) with eng.connect() as conn: eq_(conn.get_isolation_level(), self._default_isolation_level())
def test_register_base(self): registry.register("mockdialect", __name__, "MockDialect") e = create_engine("mockdialect://") assert isinstance(e.dialect, MockDialect)
def test_register_dotted(self): registry.register("mockdialect.foob", __name__, "MockDialect") e = create_engine("mockdialect+foob://") assert isinstance(e.dialect, MockDialect)
def test_register_per_dbapi(self): registry.register("mysql.my_mock_dialect", __name__, "MockDialect") e = create_engine("mysql+my_mock_dialect://") assert isinstance(e.dialect, MockDialect)