jeancochrane / jeancochrane/pytest-flask-sqlalchemy

Can't connect to MSSQL database pyodbc.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

Open
#58 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
253
Forks
45
PR merge metrics
No merged PRs in 30d

Description

Hi, I've trying to connect to my real MSSQL database in docker with the following fixtures. I omit the DB creation part for now just to simplify things. But I can't connect even to the existed database.
```

@pytest.fixture(scope="session")
def app():
app = create_app(config_class=TestingConfig)
return app

@pytest.fixture(scope="session")
def _db(app):
"""
Provide the transactional fixtures with access to the database via
a Flask-SQLAlchemy database connection.
"""
db = SQLAlchemy(app=app)

return db
```
I've tried to use different `connection timeout` settings but still have the `Login timeout expired` error
Full stacktrace:

```

ERROR
test setup failed
self = Engine(mssql+pyodbc:///?odbc_connect=Driver%3D%7BODBC+Driver+17+for+SQL+Server%7D%3BServer%3Dtcp%3Adb%2C1433%3BDatabase%3Dsqldb-web-prod-001%3BUid%3Dsa%3BPwd%3DCl1mat3m1nd%21%3BEncrypt%3Dno%3BTrustServerCertificate%3Dno%3B)
fn = >
connection = None

def _wrap_pool_connect(self, fn, connection):
dialect = self.dialect
try:
> return fn()

/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:2338:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =

def unique_connection(self):
"""Produce a DBAPI connection that is not referenced by any
thread-local context.

This method is equivalent to :meth:`_pool.Pool.connect` when the
:paramref:`_pool.Pool.use_threadlocal` flag is not set to True.
When :paramref:`_pool.Pool.use_threadlocal` is True, the
:meth:`_pool.Pool.unique_connection`
method provides a means of bypassing
the threadlocal context.

"""
> return _ConnectionFairy._checkout(self)

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:304:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cls =
pool =
threadconns = None, fairy = None

@classmethod
def _checkout(cls, pool, threadconns=None, fairy=None):
if not fairy:
> fairy = _ConnectionRecord.checkout(pool)

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:778:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cls =
pool =

@classmethod
def checkout(cls, pool):
> rec = pool._do_get()

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:495:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =

def _do_get(self):
use_overflow = self._max_overflow > -1

try:
wait = use_overflow and self._overflow >= self._max_overflow
return self._pool.get(wait, self._timeout)
except sqla_queue.Empty:
# don't do things inside of "except Empty", because when we say
# we timed out or can't connect and raise, Python 3 tells
# people the real error is queue.Empty which it isn't.
pass
if use_overflow and self._overflow >= self._max_overflow:
if not wait:
return self._do_get()
else:
raise exc.TimeoutError(
"QueuePool limit of size %d overflow %d reached, "
"connection timed out, timeout %d"
% (self.size(), self.overflow(), self._timeout),
code="3o7r",
)

if self._inc_overflow():
try:
return self._create_connection()
except:
with util.safe_reraise():
> self._dec_overflow()

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/impl.py:140:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
type_ = None, value = None, traceback = None

def __exit__(self, type_, value, traceback):
# see #2703 for notes
if type_ is None:
exc_type, exc_value, exc_tb = self._exc_info
self._exc_info = None # remove potential circular references
if not self.warn_only:
> compat.raise_(
exc_value, with_traceback=exc_tb,
)

/usr/local/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py:68:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

def raise_(
exception, with_traceback=None, replace_context=None, from_=False
):
r"""implement "raise" with cause support.

:param exception: exception to raise
:param with_traceback: will call exception.with_traceback()
:param replace_context: an as-yet-unsupported feature. This is
an exception object which we are "replacing", e.g., it's our
"cause" but we don't want it printed. Basically just what
``__suppress_context__`` does but we don't want to suppress
the enclosing context, if any. So for now we make it the
cause.
:param from\_: the cause. this actually sets the cause and doesn't
hope to hide it someday.

"""
if with_traceback is not None:
exception = exception.with_traceback(with_traceback)

if from_ is not False:
exception.__cause__ = from_
elif replace_context is not None:
# no good solution here, we would like to have the exception
# have only the context of replace_context.__context__ so that the
# intermediary exception does not change, but we can't figure
# that out.
exception.__cause__ = replace_context

try:
> raise exception

/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =

def _do_get(self):
use_overflow = self._max_overflow > -1

try:
wait = use_overflow and self._overflow >= self._max_overflow
return self._pool.get(wait, self._timeout)
except sqla_queue.Empty:
# don't do things inside of "except Empty", because when we say
# we timed out or can't connect and raise, Python 3 tells
# people the real error is queue.Empty which it isn't.
pass
if use_overflow and self._overflow >= self._max_overflow:
if not wait:
return self._do_get()
else:
raise exc.TimeoutError(
"QueuePool limit of size %d overflow %d reached, "
"connection timed out, timeout %d"
% (self.size(), self.overflow(), self._timeout),
code="3o7r",
)

if self._inc_overflow():
try:
> return self._create_connection()

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/impl.py:137:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =

def _create_connection(self):
"""Called by subclasses to create a new ConnectionRecord."""

> return _ConnectionRecord(self)

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:309:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
pool = , connect = True

def __init__(self, pool, connect=True):
self.__pool = pool
if connect:
> self.__connect(first_connect_check=True)

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:440:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
first_connect_check = True

def __connect(self, first_connect_check=False):
pool = self.__pool

# ensure any existing connection is removed, so that if
# creator fails, this attribute stays None
self.connection = None
try:
self.starttime = time.time()
connection = pool._invoke_creator(self)
pool.logger.debug("Created new connection %r", connection)
self.connection = connection
except Exception as e:
with util.safe_reraise():
> pool.logger.debug("Error on connect(): %s", e)

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:661:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
type_ = None, value = None, traceback = None

def __exit__(self, type_, value, traceback):
# see #2703 for notes
if type_ is None:
exc_type, exc_value, exc_tb = self._exc_info
self._exc_info = None # remove potential circular references
if not self.warn_only:
> compat.raise_(
exc_value, with_traceback=exc_tb,
)

/usr/local/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py:68:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

def raise_(
exception, with_traceback=None, replace_context=None, from_=False
):
r"""implement "raise" with cause support.

:param exception: exception to raise
:param with_traceback: will call exception.with_traceback()
:param replace_context: an as-yet-unsupported feature. This is
an exception object which we are "replacing", e.g., it's our
"cause" but we don't want it printed. Basically just what
``__suppress_context__`` does but we don't want to suppress
the enclosing context, if any. So for now we make it the
cause.
:param from\_: the cause. this actually sets the cause and doesn't
hope to hide it someday.

"""
if with_traceback is not None:
exception = exception.with_traceback(with_traceback)

if from_ is not False:
exception.__cause__ = from_
elif replace_context is not None:
# no good solution here, we would like to have the exception
# have only the context of replace_context.__context__ so that the
# intermediary exception does not change, but we can't figure
# that out.
exception.__cause__ = replace_context

try:
> raise exception

/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
first_connect_check = True

def __connect(self, first_connect_check=False):
pool = self.__pool

# ensure any existing connection is removed, so that if
# creator fails, this attribute stays None
self.connection = None
try:
self.starttime = time.time()
> connection = pool._invoke_creator(self)

/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:656:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

connection_record =

def connect(connection_record=None):
if dialect._has_events:
for fn in dialect.dispatch.do_connect:
connection = fn(
dialect, connection_record, cargs, cparams
)
if connection is not None:
return connection
> return dialect.connect(*cargs, **cparams)

/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/strategies.py:114:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
cargs = ('Driver={ODBC Driver 17 for SQL Server};Server=tcp:db,1433;Database=sqldb-web-prod-001;Uid=sa;Pwd=Cl1mat3m1nd!;Encrypt=no;TrustServerCertificate=no;',)
cparams = {}

def connect(self, *cargs, **cparams):
# inherits the docstring from interfaces.Dialect.connect
> return self.dbapi.connect(*cargs, **cparams)
E pyodbc.OperationalError: ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/default.py:493: OperationalError

The above exception was the direct cause of the following exception:

request = >

def fill(request):
item = request._pyfuncitem
fixturenames = getattr(item, "fixturenames", None)
if fixturenames is None:
fixturenames = request.fixturenames

if hasattr(item, 'callspec'):
for param, val in sorted_by_dependency(item.callspec.params, fixturenames):
if val is not None and is_lazy_fixture(val):
item.callspec.params[param] = request.getfixturevalue(val.name)
elif param not in item.funcargs:
item.funcargs[param] = request.getfixturevalue(param)

> _fillfixtures()

/usr/local/lib/python3.8/site-packages/pytest_lazyfixture.py:39:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/pytest_flask_sqlalchemy/fixtures.py:31: in _transaction
connection = _db.engine.connect()
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:2265: in connect
return self._connection_cls(self, **kwargs)
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:104: in __init__
else engine.raw_connection()
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:2371: in raw_connection
return self._wrap_pool_connect(
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:2341: in _wrap_pool_connect
Connection._handle_dbapi_exception_noconnection(
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:1583: in _handle_dbapi_exception_noconnection
util.raise_(
/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182: in raise_
raise exception
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/base.py:2338: in _wrap_pool_connect
return fn()
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:304: in unique_connection
return _ConnectionFairy._checkout(self)
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:778: in _checkout
fairy = _ConnectionRecord.checkout(pool)
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:495: in checkout
rec = pool._do_get()
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/impl.py:140: in _do_get
self._dec_overflow()
/usr/local/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py:68: in __exit__
compat.raise_(
/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182: in raise_
raise exception
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/impl.py:137: in _do_get
return self._create_connection()
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:309: in _create_connection
return _ConnectionRecord(self)
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:440: in __init__
self.__connect(first_connect_check=True)
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:661: in __connect
pool.logger.debug("Error on connect(): %s", e)
/usr/local/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py:68: in __exit__
compat.raise_(
/usr/local/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182: in raise_
raise exception
/usr/local/lib/python3.8/site-packages/sqlalchemy/pool/base.py:656: in __connect
connection = pool._invoke_creator(self)
/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/strategies.py:114: in connect
return dialect.connect(*cargs, **cparams)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self =
cargs = ('Driver={ODBC Driver 17 for SQL Server};Server=tcp:db,1433;Database=sqldb-web-prod-001;Uid=sa;Pwd=Cl1mat3m1nd!;Encrypt=no;TrustServerCertificate=no;',)
cparams = {}

def connect(self, *cargs, **cparams):
# inherits the docstring from interfaces.Dialect.connect
> return self.dbapi.connect(*cargs, **cparams)
E sqlalchemy.exc.OperationalError: (pyodbc.OperationalError) ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')
E (Background on this error at: http://sqlalche.me/e/13/e3q8)

/usr/local/lib/python3.8/site-packages/sqlalchemy/engine/default.py:493: OperationalError

```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.