[3] | 1 | # orm/uowdumper.py |
---|
| 2 | # Copyright (C) 2005, 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com |
---|
| 3 | # |
---|
| 4 | # This module is part of SQLAlchemy and is released under |
---|
| 5 | # the MIT License: http://www.opensource.org/licenses/mit-license.php |
---|
| 6 | |
---|
| 7 | """Dumps out a string representation of a UOWTask structure""" |
---|
| 8 | |
---|
| 9 | from sqlalchemy.orm import unitofwork |
---|
| 10 | from sqlalchemy.orm import util as mapperutil |
---|
| 11 | import StringIO |
---|
| 12 | |
---|
| 13 | class UOWDumper(unitofwork.UOWExecutor): |
---|
| 14 | def __init__(self, tasks, buf): |
---|
| 15 | self.indent = 0 |
---|
| 16 | self.tasks = tasks |
---|
| 17 | self.buf = buf |
---|
| 18 | self.execute(None, tasks) |
---|
| 19 | |
---|
| 20 | @classmethod |
---|
| 21 | def dump(cls, tasks): |
---|
| 22 | buf = StringIO.StringIO() |
---|
| 23 | UOWDumper(tasks, buf) |
---|
| 24 | return buf.getvalue() |
---|
| 25 | |
---|
| 26 | def execute(self, trans, tasks, isdelete=None): |
---|
| 27 | if isdelete is not True: |
---|
| 28 | for task in tasks: |
---|
| 29 | self._execute(trans, task, False) |
---|
| 30 | if isdelete is not False: |
---|
| 31 | for task in reversed(tasks): |
---|
| 32 | self._execute(trans, task, True) |
---|
| 33 | |
---|
| 34 | def _execute(self, trans, task, isdelete): |
---|
| 35 | try: |
---|
| 36 | i = self._indent() |
---|
| 37 | if i: |
---|
| 38 | i = i[:-1] + "+-" |
---|
| 39 | self.buf.write(i + " " + self._repr_task(task)) |
---|
| 40 | self.buf.write(" (" + (isdelete and "delete " or "save/update ") + "phase) \n") |
---|
| 41 | self.indent += 1 |
---|
| 42 | super(UOWDumper, self).execute(trans, [task], isdelete) |
---|
| 43 | finally: |
---|
| 44 | self.indent -= 1 |
---|
| 45 | |
---|
| 46 | |
---|
| 47 | def save_objects(self, trans, task): |
---|
| 48 | for rec in sorted(task.polymorphic_tosave_elements, key=lambda a: a.state.sort_key): |
---|
| 49 | if rec.listonly: |
---|
| 50 | continue |
---|
| 51 | self.buf.write(self._indent()[:-1] + "+-" + self._repr_task_element(rec) + "\n") |
---|
| 52 | |
---|
| 53 | def delete_objects(self, trans, task): |
---|
| 54 | for rec in task.polymorphic_todelete_elements: |
---|
| 55 | if rec.listonly: |
---|
| 56 | continue |
---|
| 57 | self.buf.write(self._indent() + "- " + self._repr_task_element(rec) + "\n") |
---|
| 58 | |
---|
| 59 | def execute_dependency(self, transaction, dep, isdelete): |
---|
| 60 | self._dump_processor(dep, isdelete) |
---|
| 61 | |
---|
| 62 | def _dump_processor(self, proc, deletes): |
---|
| 63 | if deletes: |
---|
| 64 | val = proc.targettask.polymorphic_todelete_elements |
---|
| 65 | else: |
---|
| 66 | val = proc.targettask.polymorphic_tosave_elements |
---|
| 67 | |
---|
| 68 | for v in val: |
---|
| 69 | self.buf.write(self._indent() + " +- " + self._repr_task_element(v, proc.processor.key, process=True) + "\n") |
---|
| 70 | |
---|
| 71 | def _repr_task_element(self, te, attribute=None, process=False): |
---|
| 72 | if getattr(te, 'state', None) is None: |
---|
| 73 | objid = "(placeholder)" |
---|
| 74 | else: |
---|
| 75 | if attribute is not None: |
---|
| 76 | objid = "%s.%s" % (mapperutil.state_str(te.state), attribute) |
---|
| 77 | else: |
---|
| 78 | objid = mapperutil.state_str(te.state) |
---|
| 79 | if process: |
---|
| 80 | return "Process %s" % (objid) |
---|
| 81 | else: |
---|
| 82 | return "%s %s" % ((te.isdelete and "Delete" or "Save"), objid) |
---|
| 83 | |
---|
| 84 | def _repr_task(self, task): |
---|
| 85 | if task.mapper is not None: |
---|
| 86 | if task.mapper.__class__.__name__ == 'Mapper': |
---|
| 87 | name = task.mapper.class_.__name__ + "/" + task.mapper.local_table.description |
---|
| 88 | else: |
---|
| 89 | name = repr(task.mapper) |
---|
| 90 | else: |
---|
| 91 | name = '(none)' |
---|
| 92 | return ("UOWTask(%s, %s)" % (hex(id(task)), name)) |
---|
| 93 | |
---|
| 94 | def _repr_task_class(self, task): |
---|
| 95 | if task.mapper is not None and task.mapper.__class__.__name__ == 'Mapper': |
---|
| 96 | return task.mapper.class_.__name__ |
---|
| 97 | else: |
---|
| 98 | return '(none)' |
---|
| 99 | |
---|
| 100 | def _indent(self): |
---|
| 101 | return " |" * self.indent |
---|