Hi, I am experimenting with storm for a personal project. So far it seems to be a great implementation. I have just completed the tutorial with modifications for multi-inheritance. I ran into a problem however with the type Accountant using ReferenceSets yielding: RuntimeError: Reference used in an unknown class when the class subclasses both Storm and another class People. When changed to only subclass from Storm it works correctly. I have attached the module that implements the problematic code (the MI subclassing for class Accountant is commented out and replaced with SI statements). I have also attached the sqlite database used, plus a summary of the execution results (MI and SI) as text file. Hope that someone can shed some light on this issue. I apologize ahead if there is some trivial error in my MI implementation. I went thru the code several times and don't see any problems. Actually everything works fine until the defined relationship "companies" is referenced. MI is also used with the Employee class, subclassing the same way as intended with Accountant. The Employee class works fine, however there are no ReferenceSet declarations in Employee. Thanks, Boris
Single-inheritance Case - This one DOES work:
class Accountant(sl.Storm):
__storm_table__ = 'accountant'
id = sl.Int(primary=True)
name = sl.Unicode()
age = sl.Int()
companies = sl.ReferenceSet(id,
'CompanyAccountant.accountant_id',
'CompanyAccountant.company_id',
'Company.id'
)
def __init__(self, name):
self.name = name
C:\>c:\Python26\python.exe
Python 2.6.1 (r261:67517, Dec 4 2008, 16:51:00) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_stormtut_classStorm as tut
>>> store = tut.createDB('sqlite:company.db')
>>> sweets = store.find(tut.Company, tut.Company.name == u"Sweets, Inc.").one()
>>> karl = store.find(tut.Accountant, tut.Accountant.name.like(u'Karl%')).one()
>>> [act.name for act in sweets.accountants]
[u'Karl Kent', u'Mark Maker']
>>> [co.name for co in karl.companies]
[u'Circus, Inc.', u'Sweets, Inc.']
>>>
Multi-inheritance Case - This one DOES NOT work:
class Accountant(sl.Storm, Person):
'''Accountant - Creates type Accountant derived from Person.
Creates an Accountant type inheriting attributes:
id
name
age
'''
__storm_table__ = 'accountant'
id = sl.Int(primary=True)
name = sl.Unicode()
age = sl.Int()
companies = sl.ReferenceSet(id,
'CompanyAccountant.accountant_id',
'CompanyAccountant.company_id',
'Company.id'
)
def __init__(self, *args, **kwargs):
super(Accountant, self).__init__(*args, **kwargs)
self.name = kwargs['name']
C:\>c:\Python26\python.exe
Python 2.6.1 (r261:67517, Dec 4 2008, 16:51:00) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_stormtut_classStorm as tut
>>> store = tut.createDB('sqlite:company.db')
>>> sweets = store.find(tut.Company, tut.Company.name == u"Sweets, Inc.").one()
>>> karl = store.find(tut.Accountant, tut.Accountant.name.like(u'Karl%')).one()
>>> [act.name for act in sweets.accountants]
[u'Karl Kent', u'Mark Maker']
>>> [co.name for co in karl.companies]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python26\lib\site-packages\storm\references.py", line 239, in __get__
if self._relation2 is None:
File "C:\Python26\lib\site-packages\storm\references.py", line 48, in __get__
getattr(obj, self._attr_builder)()
File "C:\Python26\lib\site-packages\storm\references.py", line 249, in _build_
relations
self._local_key1 = resolver.resolve(self._local_key1)
File "C:\Python26\lib\site-packages\storm\references.py", line 878, in resolve
return (self.resolve_one(properties),)
File "C:\Python26\lib\site-packages\storm\references.py", line 887, in resolve
_one
return _find_descriptor_obj(self._used_cls, property)
File "C:\Python26\lib\site-packages\storm\references.py", line 916, in _find_d
escriptor_obj
raise RuntimeError("Reference used in an unknown class")
RuntimeError: Reference used in an unknown class
>>>
#!/usr/bin/env python
'''Project: Life - Something From Nothing or Almost Nothing
Python: 2.6
Module: test_stormtut_classStorm.py
Description:
Experimental module to test ORM Storm implementation. Uses the
Storm tutorial (https://storm.canonical.com/Tutorial). Subclassing
Storm to allow for class references before their definition.
Imports:
import storm.locals as sl
Implementation:
Class: Person(object)
Methods:
__init__(self, *args, **kwargs)
Class: Employee(sl.Storm, Person)
Methods:
__init__(self, *args, **kwargs)
Class: Company(sl.Storm)
Methods:
__init__(self, name)
Class: Accountant(sl.Storm, Person)
Methods:
__init__(self, *args, **kwargs)
Class: CompanyAccountant(sl.Storm)
Methods: None
Functions:
createDB(name='sqlite:')
Dependencies:
Storm 0.14+ - Canonical Object-Relational Mapper (ORM) extension (egg).
Change log:
0.0.1 -- 2009/06/22 initial capabilities release.
TODO: Nothing
$Id:$
'''
import storm.locals as sl
class Person(object):
'''Person - Creates a base type Person.
Creates a Person type with attributes:
id
name
age
Person is not mapped to a database table; it is a base class to create
a Person derived Employee, Accountant, etc.
'''
id = sl.Int(primary=True)
name = sl.Unicode()
age = sl.Int()
def __init__(self, *args, **kwargs):
'''Initialize - Constructor initializer.
A do nothing initializer to allign super calls from subclassing
initializers
in multiple inheritance.
super(<class_name>, self).__init__(*args, **kwargs)
'''
pass
class Employee(sl.Storm, Person):
'''Employee - Creates type Employee derived from Person.
Creates an Employee type with attribute:
company_id
and inherits attributes:
id
name
age
The type is mapped to a database table via storm ORM "__storm_table__".
Enforces attribute name; an employee must have name.
'''
__storm_table__ = 'employee'
company_id = sl.Int()
company = sl.Reference(company_id,
'Company.id') # ref Company before class def
def __init__(self, *args, **kwargs):
'''Initialize - Constructor initializer.
Makes attribute name mandatory for type Employee; an employee
must have
a name.
'''
super(Employee, self).__init__(*args, **kwargs)
self.name = kwargs['name']
class Company(sl.Storm):
'''Company - Creates a base type Company.
Creates a Company type with attributes:
id
name
location
The type is mapped to a database table via storm ORM "__storm_table__".
Enforces attribute name; a company must have name.
'''
__storm_table__ = 'company'
id = sl.Int(primary=True)
name = sl.Unicode()
location = sl.Unicode()
employees = sl.ReferenceSet(id,
'Employee.company_id'
)
# ref existing Employee class
accountants = sl.ReferenceSet(id,
'CompanyAccountant.company_id',
'CompanyAccountant.accountant_id',
'Accountant.id'
)
# ref CompanyAccountant before def
def __init__(self, name):
'''Initialize - Constructor initializer.
Makes attribute name mandatory for type Company; a company must
have
a name.
'''
self.name = name
#class Accountant(sl.Storm, Person):
class Accountant(sl.Storm):
'''Accountant - Creates type Accountant derived from Person.
Creates an Accountant type inheriting attributes:
id
name
age
The type is mapped to a database table via storm ORM "__storm_table__".
Enforces attribute name; an accountant must have name.
'''
__storm_table__ = 'accountant'
id = sl.Int(primary=True)
name = sl.Unicode()
age = sl.Int()
companies = sl.ReferenceSet(id,
'CompanyAccountant.accountant_id',
'CompanyAccountant.company_id',
'Company.id'
)
# ref CompanyAccountant before def
# def __init__(self, *args, **kwargs):
def __init__(self, name):
'''Initialize - Constructor initializer.
Makes attribute name mandatory for type Accountant; an
accountant must have
a name.
'''
# super(Accountant, self).__init__(*args, **kwargs)
# self.name = kwargs['name']
self.name = name
class CompanyAccountant(sl.Storm):
'''CompanyAccountant - Creates a base type CompanyAccountant.
Creates a CompanyAccountant type with attributes:
company_id
accountant_id
The type is mapped to a database table via storm ORM "__storm_table__".
'''
__storm_table__ = 'company_accountant'
__storm_primary__ = 'company_id', 'accountant_id'
company_id = sl.Int()
accountant_id = sl.Int()
def createDB(name='sqlite:'):
'''Create DB - Creates the database and its tables.
Creates sqlite database connection and provides a storm store reference
object. If no name is provided, then a memory sqlite store is created.
Create database tables if not existing.
Returns: store
store - a Storm store db interface object; else None on error
'''
store = None
try:
db = sl.create_database(name)
store = sl.Store(db)
except OperationalError:
store = None
print('Failed to access database file {0} or invalid path.'
.format(str(name)))
except:
store = None
print('General exception, creating a database connection store
for {0}.'
.format(str(name)))
try:
if store != None:
store.execute("CREATE TABLE IF NOT EXISTS employee " +
"(id INTEGER PRIMARY KEY," +
"name VARCHAR, age INTEGER," +
"company_id INTEGER)",
noresult=True
)
store.execute("CREATE TABLE IF NOT EXISTS company " +
"(id INTEGER PRIMARY KEY," +
"name VARCHAR," +
"location VARCHAR)",
noresult=True
)
store.execute("CREATE TABLE IF NOT EXISTS accountant " +
"(id INTEGER PRIMARY KEY," +
"name VARCHAR," +
"age INTEGER)",
noresult=True
)
store.execute("CREATE TABLE IF NOT EXISTS
company_accountant " +
"(company_id INTEGER," +
"accountant_id INTEGER," +
"PRIMARY KEY (company_id, accountant_id))",
noresult=True
)
store.commit()
else: pass
except:
try:
store.rollback()
except: pass
store = None
print('Failed to create database tables for
{0}.'.format(str(name)))
return store
#EOF
company.db
Description: Binary data
-- storm mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/storm
