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

Attachment: company.db
Description: Binary data

-- 
storm mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/storm

Reply via email to