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