summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/ext/declarative
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-05-16 11:26:04 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-05-16 11:28:44 -0400
commit5039c6f01d0bd1f58f950e80cddf7472444a70a4 (patch)
treea21d629a13ef4d0f7a5129cd9fdc5f6164bfbd1e /lib/sqlalchemy/ext/declarative
parent89e6beaf46ebdd626e292eb20f7b6ae0c3a9ae5c (diff)
downloadsqlalchemy-5039c6f01d0bd1f58f950e80cddf7472444a70a4.tar.gz
Mutex the declarative scan/map process against configure_mappers()
Applied the mapper "configure mutex" against the declarative class mapping process, to guard against the race which can occur if mappers are used while dynamic module import schemes are still in the process of configuring mappers for related classes. This does not guard against all possible race conditions, such as if the concurrent import has not yet encountered the dependent classes as of yet, however it guards against as much as possible within the SQLAlchemy declarative process. Fixes: #4686 Change-Id: I0349036b8078bd42265ab40862cfbfe5bf9d5b44
Diffstat (limited to 'lib/sqlalchemy/ext/declarative')
-rw-r--r--lib/sqlalchemy/ext/declarative/base.py18
1 files changed, 12 insertions, 6 deletions
diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py
index 62db282d1..622a83736 100644
--- a/lib/sqlalchemy/ext/declarative/base.py
+++ b/lib/sqlalchemy/ext/declarative/base.py
@@ -17,6 +17,7 @@ from ... import util
from ...orm import class_mapper
from ...orm import exc as orm_exc
from ...orm import mapper
+from ...orm import mapperlib
from ...orm import synonym
from ...orm.attributes import QueryableAttribute
from ...orm.base import _is_mapped_class
@@ -155,6 +156,7 @@ class _MapperConfig(object):
cfg_cls = _DeferredMapperConfig
else:
cfg_cls = _MapperConfig
+
cfg_cls(cls_, classname, dict_)
def __init__(self, cls_, classname, dict_):
@@ -177,17 +179,21 @@ class _MapperConfig(object):
self._scan_attributes()
- clsregistry.add_class(self.classname, self.cls)
+ mapperlib._CONFIGURE_MUTEX.acquire()
+ try:
+ clsregistry.add_class(self.classname, self.cls)
- self._extract_mappable_attributes()
+ self._extract_mappable_attributes()
- self._extract_declared_columns()
+ self._extract_declared_columns()
- self._setup_table()
+ self._setup_table()
- self._setup_inheritance()
+ self._setup_inheritance()
- self._early_mapping()
+ self._early_mapping()
+ finally:
+ mapperlib._CONFIGURE_MUTEX.release()
def _early_mapping(self):
self.map()