Copy all but directories when handling hw files using preset as starting point in...
[bertos.git] / wizard / BProject.py
1 #!/usr/bin/env python
2 # encoding: utf-8
3 #
4 # This file is part of BeRTOS.
5 #
6 # Bertos is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 #
20 # As a special exception, you may use this file as part of a free software
21 # library without restriction.  Specifically, if other files instantiate
22 # templates or use macros or inline functions from this file, or you compile
23 # this file and link it with other files to produce an executable, this
24 # file does not by itself cause the resulting executable to be covered by
25 # the GNU General Public License.  This exception does not however
26 # invalidate any other reasons why the executable file might be covered by
27 # the GNU General Public License.
28 #
29 # Copyright 2008 Develer S.r.l. (http://www.develer.com/)
30 #
31 # $Id$
32 #
33 # Author: Lorenzo Berni <duplo@develer.com>
34 #
35
36 import os
37 import fnmatch
38 import copy
39 import pickle
40 import shutil
41 import copytree
42
43 import DefineException
44
45 from LoadException import VersionException, ToolchainException
46
47 import const
48
49 from bertos_utils import (
50                             # Utility functions
51                             isBertosDir, getTagSet, getInfos, updateConfigurationValues,
52                             loadConfigurationInfos, loadDefineLists, loadModuleDefinition,
53                             getCommentList, sub,
54
55                             # Project creation functions
56                             projectFileGenerator, versionFileGenerator, loadPlugin,
57                             mergeSources,
58
59                             # Custom exceptions
60                             ParseError, SupportedException
61                         )
62 import bertos_utils
63
64 from compatibility import updateProject
65
66 class BProject(object):
67     """
68     Simple class for store and retrieve project informations.
69     """
70
71     def __init__(self, project_file="", info_dict={}):
72         self.infos = {}
73         self._cached_queries = {}
74         self.edit = False
75         if project_file:
76             self.edit = True
77             self.loadBertosProject(project_file, info_dict)
78
79     #--- Load methods (methods that loads data into project) ------------------#
80
81     def loadBertosProject(self, project_file, info_dict):
82         project_dir = os.path.dirname(project_file)
83         project_data = pickle.loads(open(project_file, "r").read())
84         updateProject(project_data)
85         # If PROJECT_NAME is not defined it use the directory name as PROJECT_NAME
86         # NOTE: this can throw an Exception if the user has changed the directory containing the project
87         self.infos["PROJECT_NAME"] = project_data.get("PROJECT_NAME", os.path.basename(project_dir))
88         self.infos["PROJECT_PATH"] = os.path.dirname(project_file)
89         project_src_path = os.path.join(project_dir, project_data.get("PROJECT_SRC_PATH", project_data["PROJECT_NAME"]))
90         if project_src_path:
91             self.infos["PROJECT_SRC_PATH"] = project_src_path
92
93         else:
94             # In projects created with older versions of the Wizard this metadata doesn't exist
95             self.infos["PROJECT_SRC_PATH"] = os.path.join(self.infos["PROJECT_PATH"], self.infos["PROJECT_NAME"])
96         self.infos["PROJECT_HW_PATH"] = os.path.join(self.infos["PROJECT_PATH"], project_data.get("PROJECT_HW_PATH", self.infos["PROJECT_PATH"]))
97
98         linked_sources_path = project_data["BERTOS_PATH"]
99         sources_abspath = os.path.abspath(os.path.join(project_dir, linked_sources_path))
100         project_data["BERTOS_PATH"] = sources_abspath
101
102         self._loadBertosSourceStuff(project_data["BERTOS_PATH"], info_dict.get("BERTOS_PATH", None))
103
104         self.infos["PRESET"] = project_data.get("PRESET", False)
105
106         # For those projects that don't have a VERSION file create a dummy one.
107         if not isBertosDir(project_dir) and not self.is_preset:
108             version_file = open(os.path.join(const.DATA_DIR, "vtemplates/VERSION"), "r").read()
109             open(os.path.join(project_dir, "VERSION"), "w").write(version_file.replace("$version", "").strip())
110
111         self.loadSourceTree()
112         self._loadCpuStuff(project_data["CPU_NAME"], project_data["SELECTED_FREQ"])
113         self._loadToolchainStuff(project_data["TOOLCHAIN"], info_dict.get("TOOLCHAIN", None))
114         self.infos["OUTPUT"] = project_data["OUTPUT"]
115         self.loadModuleData(True)
116         self.setEnabledModules(project_data["ENABLED_MODULES"])
117
118     def _loadBertosSourceStuff(self, sources_path, forced_version=None):
119         if forced_version:
120             sources_path = forced_version
121         if os.path.exists(sources_path):
122             self.infos["BERTOS_PATH"] = sources_path
123         else:
124             raise VersionException(self)
125
126     def _loadCpuStuff(self, cpu_name, cpu_frequency):
127         self.infos["CPU_NAME"] = cpu_name
128         cpu_info = self.getCpuInfos()
129         for cpu in cpu_info:
130             if cpu["CPU_NAME"] == cpu_name:
131                 self.infos["CPU_INFOS"] = cpu
132                 break
133         tag_list = getTagSet(cpu_info)
134         # Create, fill and store the dict with the tags
135         tag_dict = {}
136         for element in tag_list:
137             tag_dict[element] = False
138         infos = self.info("CPU_INFOS")
139         for tag in tag_dict:
140             if tag in infos["CPU_TAGS"] + [infos["CPU_NAME"], infos["TOOLCHAIN"]]:
141                 tag_dict[tag] = True
142             else:
143                 tag_dict[tag] = False
144         self.infos["ALL_CPU_TAGS"] = tag_dict
145         self.infos["SELECTED_FREQ"] = cpu_frequency
146
147     def _loadToolchainStuff(self, toolchain, forced_toolchain=None):
148         toolchain = toolchain
149         if forced_toolchain:
150             toolchain = forced_toolchain
151         if os.path.exists(toolchain["path"]):
152             self.infos["TOOLCHAIN"] = toolchain
153         else:
154             raise ToolchainException(self)
155
156     def loadProjectFromPreset(self, preset):
157         """
158         Load a project from a preset.
159         NOTE: this is a stub.
160         """
161         project_file = os.path.join(preset, "project.bertos")
162         project_data = pickle.loads(open(project_file, "r").read())
163         self.loadSourceTree()
164         self._loadCpuStuff(project_data["CPU_NAME"], project_data["SELECTED_FREQ"])
165
166         # NOTE: this is a HACK!!!
167         # TODO: find a better way to reuse loadModuleData
168         preset_project_name = project_data.get("PROJECT_NAME", os.path.basename(preset))
169         preset_prj_src_path = os.path.join(preset, project_data.get("PROJECT_SRC_PATH", os.path.join(preset, preset_project_name)))
170         preset_prj_hw_path = os.path.join(preset, project_data.get("PROJECT_HW_PATH", preset))
171
172         old_project_name = self.infos["PROJECT_NAME"]
173         old_project_path = self.infos["PROJECT_PATH"]
174         old_project_src_path = self.infos["PROJECT_SRC_PATH"]
175         old_project_hw_path = self.infos["PROJECT_HW_PATH"]
176
177         self.infos["PROJECT_NAME"] = preset_project_name
178         self.infos["PROJECT_PATH"] = preset
179         self.infos["PROJECT_SRC_PATH"] = preset_prj_src_path
180         self.infos["PROJECT_HW_PATH"] = preset_prj_hw_path
181
182         self.loadModuleData(True)
183         self.setEnabledModules(project_data["ENABLED_MODULES"])
184
185         self.infos["PROJECT_NAME"] = old_project_name
186         self.infos["PROJECT_PATH"] = old_project_path
187         self.infos["PROJECT_SRC_PATH"] = old_project_src_path
188         self.infos["PROJECT_HW_PATH"] = old_project_hw_path
189         # End of the ugly HACK!
190
191         self.infos["PRESET_NAME"] = preset_project_name
192         self.infos["PRESET_PATH"] = preset
193         self.infos["PRESET_SRC_PATH"] = preset_prj_src_path
194         self.infos["PRESET_HW_PATH"] = preset_prj_hw_path
195
196     def loadProjectPresets(self):
197         """
198         Load the default presets (into the const.PREDEFINED_BOARDS_DIR).
199         """
200         # NOTE: this method does nothing (for now).
201         preset_path = os.path.join(self.infos["BERTOS_PATH"], const.PREDEFINED_BOARDS_DIR)
202         preset_tree = {}
203         if os.path.exists(preset_path):
204             preset_tree = self._loadProjectPresetTree(preset_path)
205         self.infos["PRESET_TREE"] = preset_tree
206
207     def _loadProjectPresetTree(self, path):
208         _tree = {}
209         _tree["info"] = self._loadPresetInfo(os.path.join(path, const.PREDEFINED_BOARD_SPEC_FILE))
210         _tree["info"]["filename"] = os.path.basename(path)
211         _tree["info"]["path"] = path
212         _tree["children"] = []
213         entries = set(os.listdir(path))
214         for entry in entries:
215             _path = os.path.join(path, entry)
216             if os.path.isdir(_path):
217                 sub_entries = set(os.listdir(_path))
218                 if const.PREDEFINED_BOARD_SPEC_FILE in sub_entries:
219                     _tree["children"].append(self._loadProjectPresetTree(_path))
220         # Add into the info dict the dir type (dir/project)
221         if _tree["children"]:
222             _tree["info"]["type"] = "dir"
223         else:
224             _tree["info"]["type"] = "project"
225         return _tree
226
227     def _loadPresetInfo(self, preset_spec_file):
228         D = {}
229         execfile(preset_spec_file, {}, D)
230         return D
231
232     def loadModuleData(self, edit=False):
233         module_info_dict = {}
234         list_info_dict = {}
235         configuration_info_dict = {}
236         file_dict = {}
237         for filename, path in self.findDefinitions("*.h") + self.findDefinitions("*.c") + self.findDefinitions("*.s") + self.findDefinitions("*.S"):
238             comment_list = getCommentList(open(path + "/" + filename, "r").read())
239             if len(comment_list) > 0:
240                 module_info = {}
241                 configuration_info = {}
242                 try:
243                     to_be_parsed, module_dict = loadModuleDefinition(comment_list[0])
244                 except ParseError, err:
245                     raise DefineException.ModuleDefineException(path, err.line_number, err.line)
246                 for module, information in module_dict.items():
247                     if "depends" not in information:
248                         information["depends"] = ()
249                     information["depends"] += (filename.split(".")[0],)
250                     information["category"] = os.path.basename(path)
251
252                     # Hack to remove 'bertos/' from the configuration file path.
253                     #
254                     # The new module information format substitute paths like 'bertos/cfg/config_file.h'
255                     # with the relative path into the bertos directory ('cfg/config_file.h')
256                     information["configuration"] = information["configuration"].replace("bertos/", "")
257                     information["hw"] = [hw.replace("bertos/", "") for hw in information["hw"]]
258
259                     if "configuration" in information and len(information["configuration"]):
260                         configuration = module_dict[module]["configuration"]
261                         try:
262                             cfg_file_path = os.path.join(self.bertos_srcdir, configuration)
263                             configuration_info[configuration] = loadConfigurationInfos(cfg_file_path)
264                         except ParseError, err:
265                             raise DefineException.ConfigurationDefineException(cfg_file_path, err.line_number, err.line)
266                         if edit:
267                             try:
268                                 path = self.infos["PROJECT_SRC_PATH"]
269                                 cfg_file_path = os.path.join(path, configuration)
270                                 configuration_info[configuration] = updateConfigurationValues(configuration_info[configuration], loadConfigurationInfos(cfg_file_path))
271                             except ParseError, err:
272                                 raise DefineException.ConfigurationDefineException(cfg_file_path, err.line_number, err.line)
273                             except IOError, err:
274                                 # The wizard can't find the file, use the default configuration
275                                 pass
276                 module_info_dict.update(module_dict)
277                 configuration_info_dict.update(configuration_info)
278                 if to_be_parsed:
279                     try:
280                         list_dict = loadDefineLists(comment_list[1:])
281                         list_info_dict.update(list_dict)
282                     except ParseError, err:
283                         raise DefineException.EnumDefineException(path, err.line_number, err.line)
284         for tag in self.infos["CPU_INFOS"]["CPU_TAGS"]:
285             for filename, path in self.findDefinitions("*_" + tag + ".h"):
286                 comment_list = getCommentList(open(path + "/" + filename, "r").read())
287                 list_info_dict.update(loadDefineLists(comment_list))
288         self.infos["MODULES"] = module_info_dict
289         self.infos["LISTS"] = list_info_dict
290         self.infos["CONFIGURATIONS"] = configuration_info_dict
291         self.infos["FILES"] = file_dict
292
293     def loadSourceTree(self):
294         """
295         Index BeRTOS source and load it in memory.
296         """
297         # Index only the BERTOS_PATH/bertos content
298         bertos_sources_dir = os.path.join(self.info("BERTOS_PATH"), "bertos")
299         file_dict = {}
300         if os.path.exists(bertos_sources_dir):
301             for element in os.walk(bertos_sources_dir):
302                 for f in element[2]:
303                     file_dict[f] = file_dict.get(f, []) + [element[0]]
304         self.infos["FILE_DICT"] = file_dict
305
306     def reloadCpuInfo(self):
307         for cpu_info in self.getCpuInfos():
308             if cpu_info["CPU_NAME"] == self.infos["CPU_NAME"]:
309                 self.infos["CPU_INFOS"] = cpu_info
310
311     #-------------------------------------------------------------------------#
312
313     def createBertosProject(self):
314         # NOTE: Temporary hack.
315         if self.edit:
316             self._editBertosProject()
317         else:
318             if not self.from_preset:
319                 self._newCustomBertosProject()
320             else:
321                 self._newBertosProjectFromPreset()
322
323     def _newBertosProject(self):
324         for directory in (self.maindir, self.srcdir, self.prjdir, self.cfgdir, self.hwdir):
325             self._createDirectory(directory)
326         # Write the project file
327         self._writeProjectFile(os.path.join(self.maindir, "project.bertos"))
328         # VERSION file
329         self._writeVersionFile(os.path.join(self.maindir, "VERSION"))
330         # Destination makefile
331         self._writeMakefile()
332         # Copy the sources
333         self._copySources(self.bertos_maindir, self.srcdir)
334         # Set properly the autoenabled parameters
335         self._setupAutoenabledParameters()
336         # Copy all the configuration files
337         self._writeCfgFiles(self.bertos_srcdir, self.cfgdir)
338         # Destination wizard mk file
339         self._writeWizardMkFile()
340
341     def _newCustomBertosProject(self):
342         # Create/write/copy the common things
343         self._newBertosProject()
344         # Copy the clean hw files
345         self._createDirectory(self.hwdir)
346         # Copy all the hw files
347         self._writeHwFiles(self.bertos_srcdir, self.hwdir)
348         # Destination user mk file
349         self._writeUserMkFile()
350         # Destination main.c file
351         self._writeMainFile(self.prjdir + "/main.c")
352         # Create project files for selected plugins
353         self._createProjectFiles()
354
355     def _newBertosProjectFromPreset(self):
356         # Create/write/copy the common things
357         self._newBertosProject()
358
359         # Copy all the files and dirs except cfg/hw/*.mk
360         self._writeCustomSrcFiles()
361
362         # Copy the hw files
363         self._writeAllPresetHwFiles(self.src_hwdir, self.hwdir)
364
365         # Copyt the new *_user.mk file
366         self._writeUserMkFileFromPreset()
367
368         if self.infos["EMPTY_MAIN"]:
369             # Create and empty main.c file only if the user check the box
370             self._writeMainFile(self.prjdir + "/main.c")
371
372         # Create project files for selected plugins
373         self._createProjectFiles()
374
375     def _editBertosProject(self):
376         # Write the project file
377         self._writeProjectFile(os.path.join(self.maindir, "project.bertos"))
378         if not self.is_preset:
379             # Generate this files only if the project isn't a preset
380             # VERSION file
381             self._writeVersionFile(os.path.join(self.maindir, "VERSION"))
382             # Destination makefile
383             self._writeMakefile()
384             # Merge sources
385             self._mergeSources(self.bertos_maindir, self.srcdir, self.old_srcdir)
386             # Copy all the hw files
387             self._writeHwFiles(self.bertos_srcdir, self.hwdir)
388             # Destination wizard mk file
389             self._writeWizardMkFile()
390         # Set properly the autoenabled parameters
391         self._setupAutoenabledParameters()
392         # Copy all the configuration files
393         self._writeCfgFiles(self.bertos_srcdir, self.cfgdir)
394         if not self.is_preset:
395             # Create project files for selected plugins only if the project isn't a preset
396             self._createProjectFiles()
397
398     def _createProjectFiles(self):
399         # Files for selected plugins
400         relevants_files = {}
401         for plugin in self.infos["OUTPUT"]:
402             module = loadPlugin(plugin)
403             relevants_files[plugin] = module.createProject(self)
404         self.infos["RELEVANT_FILES"] = relevants_files
405
406     def _writeVersionFile(self, filename):
407         if not self.edit or self.old_srcdir:
408             version_file = open(os.path.join(const.DATA_DIR, "vtemplates/VERSION"), "r").read()
409             open(filename, "w").write(versionFileGenerator(self, version_file))
410
411     def _writeProjectFile(self, filename):
412         f = open(filename, "w")
413         f.write(projectFileGenerator(self))
414         f.close()
415
416     def _writeMakefile(self):
417         bertos_utils.makefileGenerator(self)
418
419     def _writeUserMkFile(self):
420         bertos_utils.userMkGenerator(self)
421
422     def _writeUserMkFileFromPreset(self):
423         bertos_utils.userMkGeneratorFromPreset(self)
424
425     def _writeWizardMkFile(self):
426         bertos_utils.mkGenerator(self)
427
428     def _writeMainFile(self, filename):
429         main = open(os.path.join(const.DATA_DIR, "srctemplates/main.c"), "r").read()
430         open(filename, "w").write(main)
431
432     def _writeHwFiles(self, source_dir, destination_dir):
433         for module, information in self.infos["MODULES"].items():
434             for hwfile in information["hw"]:
435                 if hwfile == "":
436                     continue
437                 string = open(source_dir + "/" + hwfile, "r").read()
438                 hwfile_path = destination_dir + "/" + os.path.basename(hwfile)
439                 if not self.edit or not os.path.exists(hwfile_path):
440                     # If not in editing mode it copies all the hw files. If in
441                     # editing mode it copies only the files that don't exist yet
442                     open(os.path.join(destination_dir,os.path.basename(hwfile)), "w").write(string)
443
444     def _writeAllPresetHwFiles(self, source_dir, destination_dir):
445         """
446         Copy all but directories contained into the preset hw directory.
447         It's needed because some presets need custom hw files not defined with
448         Wizard directives into modules...
449         """
450         source_dir = os.path.join(source_dir, "hw")
451         for f in os.listdir(source_dir):
452             abspath = os.path.join(source_dir, f)
453             if not os.path.isdir(abspath):
454                 # Exlude directories from the copy!
455                 hw_file = open(os.path.join(source_dir, f), 'r').read()
456                 open(os.path.join(destination_dir, f), 'w').write(hw_file)
457
458     def _writeCfgFiles(self, source_dir, destination_dir):
459         for configuration, information in self.infos["CONFIGURATIONS"].items():
460             string = open(source_dir + "/" + configuration, "r").read()
461             for start, parameter in information["paramlist"]:
462                 infos = information[parameter]
463                 value = infos["value"]
464                 if "unsigned" in infos["informations"] and infos["informations"]["unsigned"]:
465                     value += "U"
466                 if "long" in infos["informations"] and infos["informations"]["long"]:
467                     value += "L"
468                 string = sub(string, parameter, value)
469             f = open(os.path.join(destination_dir, os.path.basename(configuration)), "w")
470             f.write(string)
471             f.close()
472
473     def _writeCustomSrcFiles(self):
474         origin = self.infos["PRESET_SRC_PATH"]
475         # Files to be ignored (all project files, cfg dir, wizard mk file, all global ignored dirs)
476         project_related_stuff = (
477             "cfg",
478             "hw",
479             self.infos["PRESET_NAME"] + ".mk",
480             self.infos["PRESET_NAME"] + "_user.mk",
481             "project.bertos",
482             self.infos["PRESET_NAME"] + ".project",
483             self.infos["PRESET_NAME"] + ".workspace",
484         ) + const.IGNORE_LIST
485         for element in os.listdir(origin):
486             if element not in project_related_stuff:
487                 full_path = os.path.join(origin, element)
488                 if os.path.isdir(full_path):
489                     copytree.copytree(full_path, os.path.join(self.prjdir, element), ignore_list=const.IGNORE_LIST)
490                 else:
491                     shutil.copy(full_path, self.prjdir)
492
493     def _setupAutoenabledParameters(self):
494         for module, information in self.infos["MODULES"].items():
495             if "configuration" in information and information["configuration"] != "":
496                 configurations = self.infos["CONFIGURATIONS"]
497                 configuration = configurations[information["configuration"]]
498                 for start, parameter in configuration["paramlist"]:
499                     if "type" in configuration[parameter]["informations"] and configuration[parameter]["informations"]["type"] == "autoenabled":
500                         configuration[parameter]["value"] = "1" if information["enabled"] else "0"
501                 self.infos["CONFIGURATIONS"] = configurations
502
503     # Project related properties
504     @property
505     def maindir(self):
506         return self.infos.get("PROJECT_PATH", None)
507
508     @property
509     def srcdir(self):
510         if self.maindir:
511             return os.path.join(self.maindir, "bertos")
512         else:
513             return None
514
515     @property
516     def prjdir(self):
517         return self.infos.get("PROJECT_SRC_PATH", None)
518
519     @property
520     def hwdir(self):
521         if self.prjdir:
522             return os.path.join(self.prjdir, "hw")
523         else:
524             return None
525
526     @property
527     def cfgdir(self):
528         if self.prjdir:
529             return os.path.join(self.prjdir, "cfg")
530         else:
531             return None
532
533     @property
534     def old_srcdir(self):
535         return self.infos.get("OLD_BERTOS_PATH", None)
536
537     # BeRTOS sources related properties
538     @property
539     def bertos_maindir(self):
540         return self.infos.get("BERTOS_PATH", None)
541
542     @property
543     def bertos_srcdir(self):
544         if self.bertos_maindir:
545             return os.path.join(self.bertos_maindir, "bertos")
546         else:
547             return None
548
549     @property
550     def src_hwdir(self):
551         if self.from_preset:
552             return os.path.join(self.infos["PRESET_PATH"], self.infos["PRESET_HW_PATH"])
553         else:
554             return self.bertos_maindir
555
556     @property
557     def from_preset(self):
558         return self.infos.get("PROJECT_FROM_PRESET", False)
559
560     @property
561     def is_preset(self):
562         return self.infos.get("PRESET", False)
563
564     def _createDirectory(self, directory):
565         if not directory:
566             return
567         if os.path.isdir(directory):
568             shutil.rmtree(directory, True)
569         os.makedirs(directory)
570
571     def _copySources(self, origin, destination):
572         # If not in editing mode it copies all the bertos sources in the /bertos subdirectory of the project
573         shutil.rmtree(destination, True)
574         copytree.copytree(origin + "/bertos", destination, ignore_list=const.IGNORE_LIST)
575
576     def _mergeSources(self, origin, destination, old_sources_dir):
577         if old_sources_dir:
578             mergeSources(destination, origin, old_sources_dir)
579
580     def setInfo(self, key, value):
581         """
582         Store the given value with the name key.
583         """
584         self.infos[key] = value
585
586     def info(self, key, default=None):
587         """
588         Retrieve the value associated with the name key.
589         """
590         if key in self.infos:
591             return copy.deepcopy(self.infos[key])
592         return default
593
594     def getCpuInfos(self):
595         cpuInfos = []
596         for definition in self.findDefinitions(const.CPU_DEFINITION):
597             cpuInfos.append(getInfos(definition))
598         return cpuInfos
599
600     def searchFiles(self, filename):
601         file_dict = self.infos["FILE_DICT"]
602         return [(filename, dirname) for dirname in file_dict.get(filename, [])]
603
604     def findDefinitions(self, ftype):
605         # Maintain a cache for every scanned BERTOS_PATH
606         definitions_dict = self._cached_queries.get(self.infos["BERTOS_PATH"], {})
607         definitions = definitions_dict.get(ftype, None)
608         if definitions is not None:
609             return definitions
610         file_dict = self.infos["FILE_DICT"]
611         definitions = []
612         for filename in file_dict:
613             if fnmatch.fnmatch(filename, ftype):
614                 definitions += [(filename, dirname) for dirname in file_dict.get(filename, [])]
615
616         # If no cache for the current BERTOS_PATH create an empty one
617         if not definitions_dict:
618             self._cached_queries[self.infos["BERTOS_PATH"]] = {}
619         # Fill the empty cache with the result
620         self._cached_queries[self.infos["BERTOS_PATH"]][ftype] = definitions
621         return definitions
622
623     def setEnabledModules(self, enabled_modules):
624         modules = self.infos["MODULES"]
625         files = {}
626         for module, information in modules.items():
627             information["enabled"] = module in enabled_modules
628             if information["enabled"]:
629                 for dependency in information["depends"]:
630                     if not dependency in modules:
631                         files[dependency] = files.get(dependency, 0) + 1
632         self.infos["MODULES"] = modules
633         self.infos["FILES"] = files
634
635     def __repr__(self):
636         return "<BProject:instance %d>%s" %(id(self), repr(self.infos))