1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
# Authors: see git history
#
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
import atexit
import os
import socket
import sys
import time
from contextlib import contextmanager
from datetime import datetime
import inkex
from lxml import etree
from .svg import line_strings_to_path
from .svg.tags import INKSCAPE_GROUPMODE, INKSCAPE_LABEL
def check_enabled(func):
def decorated(self, *args, **kwargs):
if self.enabled:
func(self, *args, **kwargs)
return decorated
class Debug(object):
def __init__(self):
self.enabled = False
self.last_log_time = None
self.current_layer = None
self.group_stack = []
def enable(self):
self.enabled = True
self.init_log()
self.init_debugger()
self.init_svg()
def init_log(self):
self.log_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), "debug.log")
# delete old content
with open(self.log_file, "w"):
pass
self.log("Debug logging enabled.")
def init_debugger(self):
# How to debug Ink/Stitch:
#
# 1. Install LiClipse (liclipse.com) -- no need to install Eclipse first
# 2. Start debug server as described here: http://www.pydev.org/manual_adv_remote_debugger.html
# * follow the "Note:" to enable the debug server menu item
# 3. Create a file named "DEBUG" next to inkstitch.py in your git clone.
# 4. Run any extension and PyDev will start debugging.
try:
import pydevd
except ImportError:
self.log("importing pydevd failed (debugger disabled)")
# pydevd likes to shout about errors to stderr whether I want it to or not
with open(os.devnull, 'w') as devnull:
stderr = sys.stderr
sys.stderr = devnull
try:
pydevd.settrace()
except socket.error as error:
self.log("Debugging: connection to pydevd failed: %s", error)
self.log("Be sure to run 'Start debugging server' in PyDev to enable debugging.")
else:
self.log("Enabled PyDev debugger.")
sys.stderr = stderr
def init_svg(self):
self.svg = etree.Element("svg", nsmap=inkex.NSS)
atexit.register(self.save_svg)
def save_svg(self):
tree = etree.ElementTree(self.svg)
debug_svg = os.path.join(os.path.dirname(os.path.dirname(__file__)), "debug.svg")
tree.write(debug_svg)
@check_enabled
def add_layer(self, name="Debug"):
layer = etree.Element("g", {
INKSCAPE_GROUPMODE: "layer",
INKSCAPE_LABEL: name,
"style": "display: none"
})
self.svg.append(layer)
self.current_layer = layer
@check_enabled
def open_group(self, name="Group"):
group = etree.Element("g", {
INKSCAPE_LABEL: name
})
self.log_svg_element(group)
self.group_stack.append(group)
@check_enabled
def close_group(self):
if self.group_stack:
self.group_stack.pop()
@check_enabled
def log(self, message, *args):
if self.last_log_time:
message = "(+%s) %s" % (datetime.now() - self.last_log_time, message)
self.raw_log(message, *args)
def raw_log(self, message, *args):
now = datetime.now()
timestamp = now.isoformat()
self.last_log_time = now
with open(self.log_file, "a") as logfile:
print(timestamp, message % args, file=logfile)
logfile.flush()
def time(self, func):
def decorated(*args, **kwargs):
if self.enabled:
self.raw_log("entering %s()", func.__name__)
start = time.time()
result = func(*args, **kwargs)
if self.enabled:
end = time.time()
self.raw_log("leaving %s(), duration = %s", func.__name__, round(end - start, 6))
return result
return decorated
@check_enabled
def log_svg_element(self, element):
if self.current_layer is None:
self.add_layer()
if self.group_stack:
self.group_stack[-1].append(element)
else:
self.current_layer.append(element)
@check_enabled
def log_line_string(self, line_string, name=None, color=None):
"""Add a Shapely LineString to the SVG log."""
self.log_line_strings([line_string], name, color)
@check_enabled
def log_line_strings(self, line_strings, name=None, color=None):
path = line_strings_to_path(line_strings)
path.set('style', str(inkex.Style({"stroke": color or "#000000", "stroke-width": "0.3"})))
if name is not None:
path.set(INKSCAPE_LABEL, name)
self.log_svg_element(path)
@check_enabled
def log_line(self, start, end, name="line", color=None):
self.log_svg_element(etree.Element("path", {
"d": "M%s,%s %s,%s" % (start + end),
"style": str(inkex.Style({"stroke": color or "#000000", "stroke-width": "0.3"})),
INKSCAPE_LABEL: name
}))
@check_enabled
def log_graph(self, graph, name="Graph", color=None):
d = ""
for edge in graph.edges:
d += "M%s,%s %s,%s" % (edge[0] + edge[1])
self.log_svg_element(etree.Element("path", {
"d": d,
"style": str(inkex.Style({"stroke": color or "#000000", "stroke-width": "0.3"})),
INKSCAPE_LABEL: name
}))
@contextmanager
def time_this(self, label="code block"):
if self.enabled:
start = time.time()
self.raw_log("begin %s", label)
yield
if self.enabled:
self.raw_log("completed %s, duration = %s", label, time.time() - start)
debug = Debug()
def enable():
debug.enable()
|