On 06/07/2010 02:56 PM, Az wrote:
>> Sounds good. Just beware that deepcopy will try to make copies of all
>> the objects referenced by your StudentUnmapped objects (assuming you
>> didn't define __deepcopy__), so you may end up copying projects,
>> supervisors, etc.
>>     
> Good point. I'm deepcopying my students, projects and supervisors
> dictionaries. But yes you're right, all of them have a reference to
> other objects.
>
> งง[Q1:] How will deepcopying the objects referenced by my
> StudentUnmapped object affect me?
>   

By default, deepcopy will make one copy of everything in the object
graph reachable by the object you feed it. The scary part is that,
unless you also pass in a /memo/ argument to each call to deepcopy, it
will copy the entire graph /every single call/. So if you deepcopy the
students dictionary and then deepcopy the projects dictionary, each
student's allocated_proj attribute will not match any instance in the
projects dictionary. This is why a use-case-specific copy function is
recommended: it is a lot easier to predict which objects will get copied
and which objects will be shared.

> I also tried another structure for elegance...
>
> class Student(object):
>       def __init__(self, ee_id, name, stream_id, overall_proby):
>               self.ee_id = ee_id
>               self.name = name
>               self.stream_id = stream_id
>               self.preferences = collections.defaultdict(set)
>               self.allocated_project = None
>               self.allocated_proj_ref = None
>               self.allocated_rank = None
>               self.own_project_id = None
>               self.own_project_sup = None
>               self.overall_proby = overall_proby
>
>       def __repr__(self):
>               return str(self)
>
>       def __str__(self):
>               return "%s %s %s: %s (OP: %s)" %(self.ee_id, self.name,
> self.allocated_rank, self.allocated_project, self.overall_proby)
>
>
> class StudentDBRecord(Student):
>       def __init__(self, student):
>               super(StudentDBRecord, self).__init__(student.ee_id,
>                                                                               
> student.name,
>                                                                               
> student.stream_id,
>                                                                               
> student.preferences,
>                                                                               
> student.allocated_project,
>                                                                               
> student.allocated_proj_ref,
>                                                                               
> student.allocated_rank,
>                                                                               
> student.own_project_id,
>                                                                               
> student.own_project_sup,
>                                                                               
> student.overall_proby)
>
> mapper(StudentDBRecord, students_table, properties={'proj_id' :
> relation(Project)})
>
> Basically, the theory was I'd do all my algorithm stuff on the Student
> objects and then after I've found an optimal solution I'll push those
> onto the StudentDBRecord table for persistence...
>   

I don't see any benefit to making StudentDBRecord inherit from Student.
Try this:

class Student(object):
    [existing definitions]

    def create_db_record(self):
        result = StudentDBRecord()
        result.ee_id = self.ee_id
        [copy over other attributes]
        return result

class StudentDBRecord(object):
    pass

> However I ended up getting the following error:
>
> #####
>
> File "Main.py", line 25, in <module>
>     prefsTableFile = 'Database/prefs-table.txt')
>   File "/Users/Azfar/Dropbox/Final Year Project/SPAllocation/
> DataReader.py", line 158, in readData
>     readProjectsFile(projectsFile)
>   File "/Users/Azfar/Dropbox/Final Year Project/SPAllocation/
> DataReader.py", line 66, in readProjectsFile
>     supervisors[ee_id] = Supervisor(ee_id, name, original_quota,
> loading_limit)
>   File "<string>", line 4, in __init__
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> state.py", line 71, in initialize_instance
>     fn(self, instance, args, kwargs)
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> mapper.py", line 1829, in _event_on_init
>     instrumenting_mapper.compile()
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> mapper.py", line 687, in compile
>     mapper._post_configure_properties()
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> mapper.py", line 716, in _post_configure_properties
>     prop.init()
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> interfaces.py", line 408, in init
>     self.do_init()
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> properties.py", line 714, in do_init
>     self._get_target()
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> properties.py", line 726, in _get_target
>     self.mapper = mapper.class_mapper(self.argument, compile=False)
>   File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/
> lib/python2.6/site-packages/SQLAlchemy-0.5.8-py2.6.egg/sqlalchemy/orm/
> util.py", line 564, in class_mapper
>     raise exc.UnmappedClassError(class_)
> sqlalchemy.orm.exc.UnmappedClassError: Class 'ProjectParties.Student'
> is not mapped
>
> #####
>
> งง[Q2:] What's that all about? Something wrong with the inheritence?
>   

I don't know if there is a way to get the inheritance to work they way
you want it, but not using inheritance like I did above sidesteps the issue.

>> I would recommend using a database
>> sequence or GUIDs to ensure that each call to monteCarloBasic gets a
>> unique value for this column.
>>     
> As another key sequence different from the simple "ident ==
> row_number" I'm currently using right? I'll look into that.
>   

The problem is that your ident always starts at 1 for each call to
monteCarloBasic. So, assuming your primary key for SimAllocation
consists of some combination of (session_id, ident, stud_id), you will
be reusing the same primary keys for each call to monteCarloBasic. If
you want to overwrite the rows with the primary keys, then you should
either DELETE the old rows first or maybe use session.merge(temp_alloc)
to get the "find or create" behavior. If you do NOT want to overwrite
the rows, then you need to ensure that some set of columns in
SimAllocation is globally unique, regardless of how many times
monteCarloBasic has been called. An easy way to do this is to change
ident to use a database sequence or GUID, but there are many other
solutions. You probably want to group together SimAllocations from a
particular call to monteCarloBasic together, in which case you would add
a run_id column to SimAllocation, where rows with the same run_id were
created in the same call to monteCarloBasic. I think a primary key of
(run_id, session_id/trial_id, stud_id) would be good.

> The thread business is indeed going over my head :S.
>
>   
>> In this way, monteCarloBasic returns its
>>      results as a set of objects that are not attached to any session
>>      (either because they are unmapped or are transient
>>      
>> <http://www.sqlalchemy.org/docs/reference/orm/sessions.html#sqlalchemy...>
>>      instances), which the UI thread uses to update the database. How
>>      you pass data from worker threads to the UI thread is dependent on
>>      your GUI toolkit.
>>     
> My GUI toolkit is Tkinter?
>   

Never used it, sorry. In general, every UI toolkit has a message/event
queue to which you can post messages from any thread. So you could do
something like:

result = monteCarloBasic(...)

def runs_in_ui_thread():
    update_database(result)

ui_toolkit.post_callback(runs_in_ui_thread)

-Conor

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

Reply via email to