difficult error from Base.metadata.create_all(engine)

1,482 views
Skip to first unread message

farcat

unread,
Mar 31, 2011, 11:29:16 AM3/31/11
to sqlalchemy
Hi,

I am getting the following error after creating a number of classes
through metaclasses:

Traceback (most recent call last):
File "D:\Documents\Code\Eclipse\workspace\SQLAtest\data.py", line
20, in <module>
createClasses(engine, session)
File "D:\Documents\Code\Eclipse\workspace\SQLAtest\src
\dataclasses.py", line 126, in createClasses
Base.metadata.create_all(engine)
File "C:\python27\lib\site-packages\sqlalchemy\schema.py", line
2148, in create_all
bind.create(self, checkfirst=checkfirst, tables=tables)
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
1698, in create
connection=connection, **kwargs)
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
1740, in _run_visitor
**kwargs).traverse_single(element)
File "C:\python27\lib\site-packages\sqlalchemy\sql\visitors.py",
line 83, in traverse_single
return meth(obj, **kw)
File "C:\python27\lib\site-packages\sqlalchemy\engine\ddl.py", line
42, in visit_metadata
self.traverse_single(table, create_ok=True)
File "C:\python27\lib\site-packages\sqlalchemy\sql\visitors.py",
line 83, in traverse_single
return meth(obj, **kw)
File "C:\python27\lib\site-packages\sqlalchemy\engine\ddl.py", line
58, in visit_table
self.connection.execute(schema.CreateTable(table))
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
1191, in execute
params)
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
1241, in _execute_ddl
compiled_ddl=ddl.compile(dialect=self.dialect),
File "C:\python27\lib\site-packages\sqlalchemy\sql\expression.py",
line 1413, in compile
compiler.compile()
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
702, in compile
self.string = self.process(self.statement)
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
715, in process
return obj._compiler_dispatch(self, **kwargs)
File "C:\python27\lib\site-packages\sqlalchemy\sql\visitors.py",
line 54, in _compiler_dispatch
return getter(visitor)(self, **kw)
File "C:\python27\lib\site-packages\sqlalchemy\sql\compiler.py",
line 1160, in visit_create_table
const = self.create_table_constraints(table)
File "C:\python27\lib\site-packages\sqlalchemy\sql\compiler.py",
line 1178, in create_table_constraints
(self.process(constraint) for constraint in constraints
File "C:\python27\lib\site-packages\sqlalchemy\sql\compiler.py",
line 1177, in <genexpr>
return ", \n\t".join(p for p in
File "C:\python27\lib\site-packages\sqlalchemy\sql\compiler.py",
line 1184, in <genexpr>
not getattr(constraint, 'use_alter', False)
File "C:\python27\lib\site-packages\sqlalchemy\engine\base.py", line
715, in process
return obj._compiler_dispatch(self, **kwargs)
File "C:\python27\lib\site-packages\sqlalchemy\sql\visitors.py",
line 54, in _compiler_dispatch
return getter(visitor)(self, **kw)
File "C:\python27\lib\site-packages\sqlalchemy\dialects\sqlite
\base.py", line 280, in visit_foreign_key_constraint
if local_table.schema != remote_table.schema:
AttributeError: 'NoneType' object has no attribute 'schema'

Before I paste in any code (would need quite a lot), can anyone point
me in the right direction?


Michael Bayer

unread,
Mar 31, 2011, 11:33:28 AM3/31/11
to sqlal...@googlegroups.com

On Mar 31, 2011, at 11:29 AM, farcat wrote:

> Hi,
>
> I am getting the following error after creating a number of classes
> through metaclasses:
>

> File "C:\python27\lib\site-packages\sqlalchemy\dialects\sqlite
> \base.py", line 280, in visit_foreign_key_constraint
> if local_table.schema != remote_table.schema:
> AttributeError: 'NoneType' object has no attribute 'schema'
>
> Before I paste in any code (would need quite a lot), can anyone point
> me in the right direction?

There's a Column not attached to a Table somewhere. Like, if you are creating a copy of a column, giving that to a table, but then the original is what you put in ForeignKey.

>
>
> --
> You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
> To post to this group, send email to sqlal...@googlegroups.com.
> To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
>

farcat

unread,
Apr 1, 2011, 2:52:24 PM4/1/11
to sqlalchemy
Hi Michael,

Still stuck, I don't mixin foreign keys or relationships. When is a
Column attached to a table in declarative?

My code is:

import datetime
from datatypes import *
from accessors import member_accessor, reference_accessor

from sqlalchemy import *
from sqlalchemy.orm import relationship
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.ext.declarative import declared_attr, DeclarativeMeta
from sqlalchemy.types import Text, BigInteger, Float, Boolean, Date,
Time
#---------------------------------------------------------------------------
engine = create_engine('sqlite:///:memory:', echo=False)
Session = sessionmaker(bind=engine)
register = dict()

#---------------------------------------------------------------------------
class BaseBase(object):
session = Session()
@declared_attr
def __tablename__(cls): return cls.__name__
def __init__(self, **kwargs):
Base.__init__(self, **kwargs)
self.session.add(self)
print str(self) + " added to session " + str(self.session)
def __repr__(self):
out = "type: " + type(self).__name__ + "{"
for name, mem in self.__dict__:
out += name + ": " + str(mem) + ", "
out += "}"
return out

#--------------------------------------------------------------------
class AtomBase(BaseBase):
id = Column(Integer, primary_key=True)
atomic = True
#--------------------------------------------------------------------
class atommeta(DeclarativeMeta):
def __new__(mcls, name, coltype):
return DeclarativeMeta.__new__(mcls, name, (AtomBase, Base),
{name:Column(coltype, nullable = False)})
def __init__(cls, name, coltype):
register[name] = cls
return DeclarativeMeta.__init__(cls, name, (AtomBase, Base),
{})
#---------------------------------------------------------------------------
class BaseLink(BaseBase):

member_name = Column(String(64), primary_key = True) #Name of
member of parent class
member_table = Column(String(64), primary_key = True) #Name of
table in which value of member resides
member_id = Column(Integer, primary_key = True) #record
is in member_table, with previous column enables polymorphism
def _getitem(self):
t = register[self.member_table]
return self.session.query(t).filter(self.member_id ==
t.id).one()
def _setitem(self, val):
try: del self.item
except AttributeError: pass
self.member_table = val.__tablename__
self.member_id = val.id
def _delitem(self):
t = register[self.member_table]
self.session.query(t).filter(t.id == self.member_id).delete()
item = property(_getitem, _setitem, _delitem)
#---------------------------------------------------------------------------
class BaseTable(BaseBase):

id = Column(Integer, primary_key = True)
created_at = Column(DateTime, default=datetime.datetime.now())
atomic = False
#---------------------------------------------------------------------------
class linkmeta(DeclarativeMeta):
def __new__(mcls, parent):
return DeclarativeMeta.__new__(mcls, "%s_links" %
parent.__name__, (BaseLink, Base),
{"parent_id": Column(Integer,
ForeignKey(parent.id), primary_key=True)})
def __init__(cls, parent):
return DeclarativeMeta.__init__(cls, "%s_links" %
parent.__name__, (BaseLink, Base), {})
#---------------------------------------------------------------------------
class tablemeta(DeclarativeMeta):

def __new__(mcls, typedef):
out = DeclarativeMeta.__new__(mcls, str(typedef.name),
(BaseTable,Base), {})
out.links = linkmeta(out) #<== Creates class/table enables
links to other tables
members = typedef.all()
for mem in members:
if not mem.type.name in register:
tablemeta(mem.type)
setattr(out, "_" + mem.name, relationship(out.links,
uselist =
(mem.multiplicity != "one"),
backref =
mem.name,
primaryjoin =
and_(out.links.parent_id == out.id,

out.links.member_name == mem.name)))
return out
def __init__(cls, typedef):
register[cls.__name__] = cls
temp = dict()
members = typedef.all()
for mem in members:
if mem.reference:
temp[mem.name] = reference_accessor(mem.name,
register[mem.type_name], mem.multiplicity)
else:
temp[mem.name] = member_accessor(mem.name,
register[mem.type_name], mem.multiplicity)
return DeclarativeMeta.__init__(cls, typedef.name,
(BaseTable,Base), temp)
#---------------------------------------------------------------------------
def createClasses(engine, session):
print "creating classes and tables"
atommeta("text", Text)
atommeta("integer", BigInteger)
atommeta("decimal", Float)
atommeta("boolean", Boolean)
atommeta("date", Date)
atommeta("time", Time)
typedefs = session.query(Type).filter(Type.atomic == False).all()
for typedef in typedefs:
tablemeta(typedef)
print
"-----------------------------------------------------------------------------------"
for reg in register:
print reg
Base.metadata.create_all(engine) #<== ERROR
print"done"

Please help ....

The typedefs variables describe classes and members, and are queried
from normal tables

Michael Bayer

unread,
Apr 1, 2011, 8:09:31 PM4/1/11
to sqlal...@googlegroups.com

On Apr 1, 2011, at 2:52 PM, farcat wrote:

> Hi Michael,
>
> Still stuck, I don't mixin foreign keys or relationships. When is a
> Column attached to a table in declarative?
>

so you have a few things like:

> class AtomBase(BaseBase):
> id = Column(Integer, primary_key=True)

where AtomBase does not appear to be a declarative class. Its hard to follow but it appears AtomBase is taking the path that mixins take in declarative (indeed: "__new__(mcls, name, (AtomBase, Base)"). This means "id" will be copied for each actual declarative class generated from AtomBase.

Later you have:

> ForeignKey(parent.id),

This is referencing an "id" column probably too early. In all likelihood It isn't being linked to a table, a copy of it is. Use ForeignKey("parent_table_name.id") instead so that the column is evaluated as late as possible.

farcat

unread,
Apr 2, 2011, 5:56:23 AM4/2/11
to sqlalchemy
He Michael,

You saved me again .. Thanks!

farcat

unread,
Apr 2, 2011, 8:59:54 AM4/2/11
to sqlalchemy
Hello,

I get the following error:
_______________________________________
Traceback (most recent call last):
File "D:\Documents\Code\Eclipse\workspace\SQLAtest\data.py", line
29, in <module>
I1 = reg["integer"](integer = 5321)
File "<string>", line 4, in __init__
File "C:\python27\lib\site-packages\sqlalchemy\orm\state.py", line
100, in initialize_instance
fn(self, instance, args, kwargs)
File "C:\python27\lib\site-packages\sqlalchemy\orm\mapper.py", line
2413, in _event_on_init
instrumenting_mapper.compile()
File "C:\python27\lib\site-packages\sqlalchemy\orm\mapper.py", line
807, in compile
mapper._post_configure_properties()
File "C:\python27\lib\site-packages\sqlalchemy\orm\mapper.py", line
837, in _post_configure_properties
prop.init()
File "C:\python27\lib\site-packages\sqlalchemy\orm\interfaces.py",
line 475, in init
self.do_init()
File "C:\python27\lib\site-packages\sqlalchemy\orm\properties.py",
line 900, in do_init
self._determine_synchronize_pairs()
File "C:\python27\lib\site-packages\sqlalchemy\orm\properties.py",
line 1157, in _determine_synchronize_pairs
eq_pairs = self._sync_pairs_from_join(self.primaryjoin, True)
File "C:\python27\lib\site-packages\sqlalchemy\orm\properties.py",
line 1141, in _sync_pairs_from_join
self
sqlalchemy.exc.ArgumentError: Could not determine relationship
direction for primaryjoin condition 'False AND False', on relationship
F_Address_links.number. Ensure that the referencing Column objects
have a ForeignKey present, or are otherwise part of a
ForeignKeyConstraint on their parent Table, or specify the
foreign_keys parameter to this relationship.
____________________________________________

Strange thing is that the line "I1 = reg["integer"](integer = 5321)"
is the first object/record I create and it works when I do not create
any other classes. Also the class/table "F_Address_links" in the error
message exists but no objects/records have been created yet. For
example I do not understand how "I1 = reg["integer"](integer = 5321)"
leads to a call to a method that does anything with "F_Address_links"
or related class/table "F_Address".

Please help ... It might be related to the ForeignKey in the code I
showed earlier in this thread, but I don't see how.

farcat

unread,
Apr 3, 2011, 11:50:54 AM4/3/11
to sqlalchemy
OK,

after a long day of experimentation ... I found a solution. This is
the new code (compare to old copied in above):

------------------------------------------------------------------------------------------

class tablemeta(DeclarativeMeta):

def __new__(mcls, typedef):
return DeclarativeMeta.__new__(mcls, str(typedef.name),
(BaseTable,Base), {})
def __init__(cls, typedef):
reg[cls.__name__] = cls
cls.links = linkmeta(typedef)
DeclarativeMeta.__init__(cls, typedef.name, (BaseTable,Base),
{}) #<== FIRST
members = typedef.all()
cls.__setlinks(members) #<== ADD RELATIONSHIPS

def __setlinks(cls, members):
for mem in members:
setattr(cls, "_" + mem.name, relationship(cls.links,
uselist =
(mem.multiplicity != "one"),
backref =
mem.name,
primaryjoin =
and_(cls.links.parent_id == cls.id,

cls.links.member_name == mem.name)))
-----------------------------------------------------------------------------------------------------------------
The problem seemed to be in the order of adding relationships. The
main difference is that now i call DeclarativeMeta.__init__ before
adding relationships. Even using a dict with relationship attributes
as last argument to __init__ did not work.( BTW cls.links is a table/
class used for references to records in dynamic other tables.)

Hope this helps someone in the future; the error messages can be very
confusing.
> ...
>
> read more »

Michael Bayer

unread,
Apr 3, 2011, 12:53:00 PM4/3/11
to sqlal...@googlegroups.com

On Apr 3, 2011, at 11:50 AM, farcat wrote:

> The problem seemed to be in the order of adding relationships. The
> main difference is that now i call DeclarativeMeta.__init__ before
> adding relationships. Even using a dict with relationship attributes
> as last argument to __init__ did not work.( BTW cls.links is a table/
> class used for references to records in dynamic other tables.)

The declarative metaclass itself receives relationship() objects and initializes them just fine when used normally. It appears like you were creating a relationship() passing in non-SQL expression objects (i.e. not Column objects or similar), so an expression like "x==y" would just be False.

farcat

unread,
Apr 3, 2011, 4:01:09 PM4/3/11
to sqlalchemy
Hi Michael,

Could "cls.links.member_name == mem.name" have been the problem?
"mem.name" is just a string. "cls" and "cls.links" are classes/tables
(links is just an extra attribute in cls).

Regards, Lars

Ce
> ...
>
> read more »
Reply all
Reply to author
Forward
0 new messages