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 |
---|