summaryrefslogtreecommitdiff
path: root/lib/debug.py
blob: 05c367f0ccf694b90841ad73d50ae2b919c51267 (plain)
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
import atexit
from datetime import datetime
import os
import socket
import sys
import time

from inkex import etree
import inkex
from simplestyle import formatStyle

from svg import line_strings_to_path
from svg.tags import INKSCAPE_GROUPMODE, INKSCAPE_LABEL


class Debug(object):
    def __init__(self):
        self.last_log_time = None
        self.current_layer = None

    def enable(self):
        self.enable_log()
        self.enable_debugger()
        self.enable_svg()

    def enable_log(self):
        self.log = self._log
        self.raw_log = self._raw_log
        self.log_file = open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "debug.log"), "w")
        self.log("Debug logging enabled.")

    def enable_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, 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 enable_svg(self):
        self.svg = etree.Element("svg", nsmap=inkex.NSS)
        atexit.register(self.save_svg)

    def save_svg(self):
        tree = etree.ElementTree(self.svg)
        with open(os.path.join(os.path.dirname(os.path.dirname(__file__)), "debug.svg"), "w") as debug_svg:
            tree.write(debug_svg)

    def add_layer(self, name="Debug"):
        layer = etree.Element("g", {
            INKSCAPE_GROUPMODE: "layer",
            INKSCAPE_LABEL: name
        })
        self.svg.append(layer)
        self.current_layer = layer

    def _noop(self, *args, **kwargs):
        pass

    log = _noop
    raw_log = _noop

    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

        print >> self.log_file, timestamp, message % args
        self.log_file.flush()

    def time(self, func):
        def decorated(*args, **kwargs):
            self.raw_log("entering %s()", func.func_name)
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            self.raw_log("leaving %s(), duration = %s", func.func_name, round(end - start, 6))
            return result

        return decorated

    def log_svg_element(self, element):
        if self.current_layer is None:
            self.add_layer()

        self.current_layer.append(element)

    def log_line_string(self, line_string, color="#000000"):
        """Add a Shapely LineString to the SVG log."""
        self.log_line_strings(self, [line_string])

    def log_line_strings(self, line_strings, color="#000000"):
        path = line_strings_to_path(line_strings)
        path.set('style', formatStyle({"stroke": color, "stroke-width": "0.3"}))
        self.log_svg_element(path)


debug = Debug()
enable = debug.enable