chiark / gitweb /
Allow back in the configuration wizard.
[cura.git] / Cura / util / plugin.py
1 """
2 The plugin module contains information about the plugins found for Cura.
3 It keeps track of a list of installed plugins and the information contained within.
4 """
5 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
6
7 import os
8 import sys
9 import traceback
10 import platform
11 import re
12 import tempfile
13 import cPickle as pickle
14
15 from Cura.util import profile
16 from Cura.util import resources
17
18 _pluginList = None
19
20 class pluginInfo(object):
21         def __init__(self, dirname, filename):
22                 self._dirname = dirname
23                 self._filename = filename
24                 self._name = os.path.splitext(os.path.basename(filename))[0]
25                 self._type = 'unknown'
26                 self._info = ''
27                 self._params = []
28                 with open(os.path.join(dirname, filename), "r") as f:
29                         for line in f:
30                                 line = line.strip()
31                                 if not line.startswith('#'):
32                                         break
33                                 line = line[1:].split(':', 1)
34                                 if len(line) != 2:
35                                         continue
36                                 if line[0].upper() == 'NAME':
37                                         self._name = line[1].strip()
38                                 elif line[0].upper() == 'INFO':
39                                         self._info = line[1].strip()
40                                 elif line[0].upper() == 'TYPE':
41                                         self._type = line[1].strip()
42                                 elif line[0].upper() == 'DEPEND':
43                                         pass
44                                 elif line[0].upper() == 'PARAM':
45                                         m = re.match('([a-zA-Z][a-zA-Z0-9_]*)\(([a-zA-Z_]*)(?::([^\)]*))?\) +(.*)', line[1].strip())
46                                         if m is not None:
47                                                 self._params.append({'name': m.group(1), 'type': m.group(2), 'default': m.group(3), 'description': m.group(4)})
48                                 # else:
49                                 #       print "Unknown item in plugin meta data: %s %s" % (line[0], line[1])
50
51         def getFilename(self):
52                 return self._filename
53
54         def getFullFilename(self):
55                 return os.path.join(self._dirname, self._filename)
56
57         def getType(self):
58                 return self._type
59
60         def getName(self):
61                 return self._name
62
63         def getInfo(self):
64                 return self._info
65
66         def getParams(self):
67                 return self._params
68
69 def getPostProcessPluginConfig():
70         try:
71                 return pickle.loads(str(profile.getProfileSetting('plugin_config')))
72         except:
73                 return []
74
75 def setPostProcessPluginConfig(config):
76         profile.putProfileSetting('plugin_config', pickle.dumps(config))
77
78 def getPluginBasePaths():
79         ret = []
80         if platform.system() != "Windows":
81                 ret.append(os.path.expanduser('~/.cura/plugins/'))
82         if platform.system() == "Darwin" and hasattr(sys, 'frozen'):
83                 ret.append(os.path.normpath(os.path.join(resources.resourceBasePath, "plugins")))
84         else:
85                 ret.append(os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'plugins')))
86         return ret
87
88 def getPluginList(pluginType):
89         global _pluginList
90         if _pluginList is None:
91                 _pluginList = []
92                 for basePath in getPluginBasePaths():
93                         for filename in os.listdir(basePath):
94                                 if filename.startswith('.'):
95                                         continue
96                                 if filename.startswith('_'):
97                                         continue
98                                 if os.path.isdir(os.path.join(basePath, filename)):
99                                         if os.path.exists(os.path.join(basePath, filename, 'script.py')):
100                                                 _pluginList.append(pluginInfo(basePath, os.path.join(filename, 'script.py')))
101                                 elif filename.endswith('.py'):
102                                         _pluginList.append(pluginInfo(basePath, filename))
103         ret = []
104         for plugin in _pluginList:
105                 if plugin.getType() == pluginType:
106                         ret.append(plugin)
107         return ret
108
109 def runPostProcessingPlugins(engineResult):
110         pluginConfigList = getPostProcessPluginConfig()
111         pluginList = getPluginList('postprocess')
112
113         tempfilename = None
114         for pluginConfig in pluginConfigList:
115                 plugin = None
116                 for pluginTest in pluginList:
117                         if pluginTest.getFilename() == pluginConfig['filename']:
118                                 plugin = pluginTest
119                 if plugin is None:
120                         continue
121
122                 pythonFile = plugin.getFullFilename()
123
124                 if tempfilename is None:
125                         f = tempfile.NamedTemporaryFile(prefix='CuraPluginTemp', delete=False)
126                         tempfilename = f.name
127                         f.write(engineResult.getGCode())
128                         f.close()
129
130                 locals = {'filename': tempfilename}
131                 for param in plugin.getParams():
132                         value = param['default']
133                         if param['name'] in pluginConfig['params']:
134                                 value = pluginConfig['params'][param['name']]
135
136                         if param['type'] == 'float':
137                                 try:
138                                         value = float(value)
139                                 except:
140                                         value = float(param['default'])
141
142                         locals[param['name']] = value
143                 try:
144                         execfile(pythonFile, locals)
145                 except:
146                         locationInfo = traceback.extract_tb(sys.exc_info()[2])[-1]
147                         return "%s: '%s' @ %s:%s:%d" % (str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]), os.path.basename(locationInfo[0]), locationInfo[2], locationInfo[1])
148         if tempfilename is not None:
149                 f = open(tempfilename, "r")
150                 engineResult.setGCode(f.read())
151                 f.close()
152                 os.unlink(tempfilename)
153         return None