| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 1 | import inspect |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame^] | 2 | from django_frame import DjangoTemplateFrame |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 3 | from pydevd_comm import CMD_SET_BREAK |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame^] | 4 | from pydevd_constants import DJANGO_SUSPEND, GetThreadId, DictContains |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 5 | from pydevd_breakpoints import LineBreakpoint |
| 6 | import pydevd_vars |
| 7 | import traceback |
| 8 | |
| 9 | class DjangoLineBreakpoint(LineBreakpoint): |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame^] | 10 | |
| 11 | def __init__(self, file, line, condition, func_name, expression): |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 12 | self.file = file |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame^] | 13 | LineBreakpoint.__init__(self, line, condition, func_name, expression) |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 14 | |
| Tor Norbye | 1aa2e09 | 2014-08-20 17:01:23 -0700 | [diff] [blame^] | 15 | def is_triggered(self, template_frame_file, template_frame_line): |
| 16 | return self.file == template_frame_file and self.line == template_frame_line |
| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame] | 17 | |
| 18 | def __str__(self): |
| 19 | return "DjangoLineBreakpoint: %s-%d" %(self.file, self.line) |
| 20 | |
| 21 | |
| 22 | def inherits(cls, *names): |
| 23 | if cls.__name__ in names: |
| 24 | return True |
| 25 | inherits_node = False |
| 26 | for base in inspect.getmro(cls): |
| 27 | if base.__name__ in names: |
| 28 | inherits_node = True |
| 29 | break |
| 30 | return inherits_node |
| 31 | |
| 32 | |
| 33 | def is_django_render_call(frame): |
| 34 | try: |
| 35 | name = frame.f_code.co_name |
| 36 | if name != 'render': |
| 37 | return False |
| 38 | |
| 39 | if not DictContains(frame.f_locals, 'self'): |
| 40 | return False |
| 41 | |
| 42 | cls = frame.f_locals['self'].__class__ |
| 43 | |
| 44 | inherits_node = inherits(cls, 'Node') |
| 45 | |
| 46 | if not inherits_node: |
| 47 | return False |
| 48 | |
| 49 | clsname = cls.__name__ |
| 50 | return clsname != 'TextNode' and clsname != 'NodeList' |
| 51 | except: |
| 52 | traceback.print_exc() |
| 53 | return False |
| 54 | |
| 55 | |
| 56 | def is_django_context_get_call(frame): |
| 57 | try: |
| 58 | if not DictContains(frame.f_locals, 'self'): |
| 59 | return False |
| 60 | |
| 61 | cls = frame.f_locals['self'].__class__ |
| 62 | |
| 63 | return inherits(cls, 'BaseContext') |
| 64 | except: |
| 65 | traceback.print_exc() |
| 66 | return False |
| 67 | |
| 68 | |
| 69 | def is_django_resolve_call(frame): |
| 70 | try: |
| 71 | name = frame.f_code.co_name |
| 72 | if name != '_resolve_lookup': |
| 73 | return False |
| 74 | |
| 75 | if not DictContains(frame.f_locals, 'self'): |
| 76 | return False |
| 77 | |
| 78 | cls = frame.f_locals['self'].__class__ |
| 79 | |
| 80 | clsname = cls.__name__ |
| 81 | return clsname == 'Variable' |
| 82 | except: |
| 83 | traceback.print_exc() |
| 84 | return False |
| 85 | |
| 86 | |
| 87 | def is_django_suspended(thread): |
| 88 | return thread.additionalInfo.suspend_type == DJANGO_SUSPEND |
| 89 | |
| 90 | |
| 91 | def suspend_django(py_db_frame, mainDebugger, thread, frame, cmd=CMD_SET_BREAK): |
| 92 | frame = DjangoTemplateFrame(frame) |
| 93 | |
| 94 | if frame.f_lineno is None: |
| 95 | return None |
| 96 | |
| 97 | #try: |
| 98 | # if thread.additionalInfo.filename == frame.f_code.co_filename and thread.additionalInfo.line == frame.f_lineno: |
| 99 | # return None # don't stay twice on the same line |
| 100 | #except AttributeError: |
| 101 | # pass |
| 102 | |
| 103 | pydevd_vars.addAdditionalFrameById(GetThreadId(thread), {id(frame): frame}) |
| 104 | |
| 105 | py_db_frame.setSuspend(thread, cmd) |
| 106 | thread.additionalInfo.suspend_type = DJANGO_SUSPEND |
| 107 | |
| 108 | thread.additionalInfo.filename = frame.f_code.co_filename |
| 109 | thread.additionalInfo.line = frame.f_lineno |
| 110 | |
| 111 | return frame |
| 112 | |
| 113 | |
| 114 | def find_django_render_frame(frame): |
| 115 | while frame is not None and not is_django_render_call(frame): |
| 116 | frame = frame.f_back |
| 117 | |
| 118 | return frame |
| 119 | |
| 120 | |
| 121 | |
| 122 | |
| 123 | |