OK, thanks for the quick answer - I guess I shouldn't be using sqlalchemy 
for the importer then, since this necessarily has to perform queries in 
order for scripts to be imported.

I might attempt restricting mapper configuration to a group of tables - I 
think the performance penalty would be quite small, as the categorization 
tests only need to be done when new mappers need configuring 
(Mapper._new_mappers == True) and should only occur once per table, but 
I'll see if this is the case.

On Tuesday, April 21, 2015 at 4:19:12 PM UTC+1, Michael Bayer wrote:
>
>  
>
> On 4/21/15 9:31 AM, Steven Winfield wrote:
>  
> Hi, 
>
>  It seems like configuration is attempted for all new mappers, globally, 
> whenever a query is done. So if library A and B both use sqlalchemy, and A 
> imports B before A's mappers can be properly initialised (e.g. there is a 
> relationship("ClassnameAsString") call somewhere that can't be resolved 
> yet), and B does something to trigger mapper configuration, then it will 
> fail. 
> This occurs even if A and B make separate calls to declarative_base(), 
> even with explicitly different metadata and bound engines. 
>  
>
> no there's not, and the short answer is that libraries shouldn't be 
> triggering mapper configuration (and definitely not doing ORM queries) at 
> import time, and/or the imports of A and B should be organized such that B 
> imports fully before A starts doing things.   Either these libraries have 
> inter-dependencies, in which case this implies mapper configuration should 
> be across all of the mappings in both, or they don't, in which case the 
> imports of A and B should not be from within each other.
>
> An enhancement that would limit configuration to groups of mappings is a 
> feasible proposal but we don't have that right now.     Wouldn't be that 
> easy to do without adding a performance penalty since the check for "new 
> mappers" would have to be limited to some categorization, meaning lookups 
> in critical sections.
>
>
>
>
>
>
>  
>  Here's a boiled-down version of the problem that I've been playing with, 
> which shows that the relationship between Parent and Child is configured 
> when a query on Test is done - even though it may be part of a different 
> library and in a different database:
>
>   from sqlalchemy import Column, Integer, Text, ForeignKey, create_engine
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy.orm import sessionmaker, relationship
> import traceback
>
>  Base1 = declarative_base()
>
>  class Test(Base1):
>     __tablename__ = "test"
>     id = Column(Integer, primary_key=True)
>
>  Base2 = declarative_base()
>
>  class Parent(Base2):
>     __tablename__ = "parent"
>     id = Column(Integer, primary_key=True)
>
>  def deferred_parent():
>     traceback.print_stack()
>     return Parent
>
>  class Child(Base2):
>     __tablename__ = "child"
>     id_parent = Column(Integer, ForeignKey(Parent.id), primary_key=True)
>     name = Column(Text, primary_key=True)
>     parent = relationship(deferred_parent)
>
>  engine = create_engine('sqlite://')
> Session = sessionmaker(bind=engine)
> session = Session()
> try:
>     session.query(Test).all()
> except:
>     pass
>
>   
>  ...the important bit of the traceback being:
>
>    File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\session.py",
>  
> line 1165, in query
>
>     return self._query_cls(entities, self, **kwargs)
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\query.py",
>  
> line 108, in __init__
>
>     self._set_entities(entities)
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\query.py",
>  
> line 118, in _set_entities
>
>     self._set_entity_selectables(self._entities)
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\query.py",
>  
> line 151, in _set_entity_selectables
>
>     ent.setup_entity(*d[entity])
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\query.py",
>  
> line 2997, in setup_entity
>
>     self._with_polymorphic = ext_info.with_polymorphic_mappers
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\util\langhelpers.py",
>  
> line 726, in __get__
>
>     obj.__dict__[self.__name__] = result = self.fget(obj)
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\mapper.py",
>  
> line 1871, in _with_polymorphic_mappers
>
>     configure_mappers()
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\mapper.py",
>  
> line 2583, in configure_mappers
>
>     mapper._post_configure_properties()
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\mapper.py",
>  
> line 1688, in _post_configure_properties
>
>     prop.init()
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\interfaces.py",
>  
> line 144, in init
>
>     self.do_init()
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\relationships.py",
>  
> line 1549, in do_init
>
>     self._process_dependent_arguments()
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\relationships.py",
>  
> line 1605, in _process_dependent_arguments
>
>     self.target = self.mapper.mapped_table
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\util\langhelpers.py",
>  
> line 726, in __get__
>
>     obj.__dict__[self.__name__] = result = self.fget(obj)
>
>   File 
> "R:\sw\external\20150407-0\python27\lib\site-packages\sqlalchemy-0.9.7-py2.7-win32.egg\sqlalchemy\orm\relationships.py",
>  
> line 1522, in mapper
>
>     argument = self.argument()
>
>   File "user!winfis!sqlalchemy!query_triggers_relationship_config.py", 
> line 19, in deferred_parent
>
>     traceback.print_stack()
>  
>  
>  Is there some method that I've missed of delaying mapper configuration? 
> Aren't the only mappers than need to be set up those that share metadata 
> with entities in the query, or any metadata bound to the engine that will 
> be used? 
> Perhaps configure_mappers() could take an optional metadata/engine and 
> only set up mappers that are related to this?
>
>  As you can see, I'm doing this with 0.9.7 but looking at the 1.0.0 code 
> I think I'd have the same problem.
>
>  
>  If it helps, (and you're not already bored) here's our use-case:
> We have one library that implements a PEP302 import hook, which fetches 
> python code from a database and compiles it. This is managed by sqlalchemy.
> Some of the code in the database also use sqlalchemy and define other sets 
> of ORM-mapped classes, completely unrelated to the first set, and which 
> relate to tables inreside in completely different databases.
> If a query needs to be executed to fetch and compile some code while 
> another set of classes are not ready to have their mappers initialised then 
> exceptions are raised.
>
>  Thanks,
> Steve.
>  -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected] <javascript:>.
> To post to this group, send email to [email protected] 
> <javascript:>.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
>
>
>  

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to