1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """
23 parsing of registry, which holds component and bundle information
24 """
25
26 import os
27 import sets
28 import stat
29 import errno
30 from StringIO import StringIO
31
32 from xml.dom import minidom, Node
33 from xml.parsers import expat
34 from xml.sax import saxutils
35
36 from flumotion.common import common, log, package, bundle, errors, fxml
37 from flumotion.configure import configure
38
39
40
41 READ_CACHE = False
42
43 __all__ = ['ComponentRegistry', 'registry']
44
46 return os.stat(file)[stat.ST_MTIME]
47
49 """
50 I represent a <component> entry in the registry
51 """
52
53
54 __pychecker__ = 'maxargs=14'
55
56 - def __init__(self, filename, type,
57 source, description, base, properties, files,
58 entries, eaters, feeders, needs_sync, clock_priority,
59 sockets):
60 """
61 @param filename: name of the XML file this component is parsed from
62 @type filename: str
63 @param properties: dict of name -> property
64 @type properties: dict of str -> L{RegistryEntryProperty}
65 @param entries: dict of entry point type -> entry
66 @type entries: dict of str -> L{RegistryEntryEntry}
67 @param sockets: list of sockets supported by the element
68 @type sockets: list of str
69 """
70 self.filename = filename
71 self.type = type
72 self.source = source
73 self.description = description
74
75 if not self.description:
76 self.description = ""
77 self.base = base
78 self.properties = properties
79 self.files = files
80 self.entries = entries
81 self.eaters = eaters
82 self.feeders = feeders
83 self.needs_sync = needs_sync
84 self.clock_priority = clock_priority
85 self.sockets = sockets
86
87 - def getProperties(self):
88 """
89 Get a list of all properties.
90
91 @rtype: list of L{RegistryEntryProperty}
92 """
93 return self.properties.values()
94
95 - def hasProperty(self, name):
96 """
97 Check if the component has a property with the given name.
98 """
99 return name in self.properties.keys()
100
101 - def getFiles(self):
103
104 - def getEntries(self):
105 return self.entries.values()
106
107 - def getEntryByType(self, type):
108 """
109 Get the entry point for the given type of entry.
110
111 @type type: string
112 """
113 return self.entries[type]
114
115 - def getGUIEntry(self):
116 if not self.files:
117 return
118
119
120 if len(self.files) > 1:
121 return
122
123 return self.files[0].getFilename()
124
127
130
131 - def getDescription(self):
132 return self.description
133
134 - def getSource(self):
136
137 - def getEaters(self):
139
140 - def getFeeders(self):
142
144 return self.needs_sync
145
147 return self.clock_priority
148
149 - def getSockets(self):
151
153 """
154 I represent a <plug> entry in the registry
155 """
156
157 - def __init__(self, filename, type, socket, entry, properties):
158 """
159 @param filename: name of the XML file this plug is parsed from
160 @type filename: str
161 @param type: the type of plug
162 @type type: str
163 @param socket: the fully qualified class name of the socket this
164 plug can be plugged in to
165 @type socket: str
166 @param entry: entry point for instantiating the plug
167 @type entry: L{RegistryEntryEntry}
168 @param properties: properties of the plug
169 @type properties: dict of str -> L{RegistryEntryProperty}
170 """
171 self.filename = filename
172 self.type = type
173 self.socket = socket
174 self.entry = entry
175 self.properties = properties
176
177 - def getProperties(self):
178 """
179 Get a list of all properties.
180
181 @rtype: list of L{RegistryEntryProperty}
182 """
183 return self.properties.values()
184
185 - def hasProperty(self, name):
186 """
187 Check if the component has a property with the given name.
188 """
189 return name in self.properties.keys()
190
191 - def getEntry(self):
193
196
197 - def getSocket(self):
199
201 "This class represents a <bundle> entry in the registry"
202 - def __init__(self, name, project, under, dependencies, directories):
203 self.name = name
204 self.project = project
205 self.under = under
206 self.dependencies = dependencies
207 self.directories = directories
208
209 - def __repr__(self):
210 return '<Bundle name=%s>' % self.name
211
214
215 - def getDependencies(self):
216 return self.dependencies
217
218 - def getDirectories(self):
219 return self.directories
220
221 - def getProject(self):
223
224 - def getUnder(self):
226
227 - def getBaseDir(self):
228 if self.project == 'flumotion':
229 return getattr(configure, self.under)
230
231 from flumotion.project import project
232 return project.get(self.project, self.under)
233
235 "This class represents a <directory> entry in the registry"
236 - def __init__(self, name, files):
237 self.name = name
238 self.files = files
239
242
243 - def getFiles(self):
245
247 "This class represents a <filename> entry in the registry"
248 - def __init__(self, location, relative):
249 self.location = location
250 self.relative = relative
251
252 - def getLocation(self):
254
255 - def getRelative(self):
257
259 "This class represents a <property> entry in the registry"
260 - def __init__(self, name, type, description, required=False, multiple=False):
261 self.name = name
262 self.type = type
263 self.description = description
264
265 if not self.description:
266 self.description = ""
267 self.required = required
268 self.multiple = multiple
269
270 - def __repr__(self):
271 return '<Property name=%s>' % self.name
272
275
278
279 - def getDescription(self):
280 return self.description
281
282 - def isRequired(self):
284
285 - def isMultiple(self):
287
288 -class RegistryEntryCompoundProperty(RegistryEntryProperty):
289 "This class represents a <compound-property> entry in the registry"
290 - def __init__(self, name, description, properties, required=False,
291 multiple=False):
292 RegistryEntryProperty.__init__(self, name, 'compound', description,
293 required, multiple)
294 self.properties = properties
295
296 - def __repr__(self):
297 return '<Compound-property name=%s>' % self.name
298
299 - def getProperties(self):
300 """
301 Get a list of all sub-properties.
302
303 @rtype: list of L{RegistryEntryProperty}
304 """
305 return self.properties.values()
306
307 - def hasProperty(self, name):
308 """
309 Check if the compound-property has a sub-property with the
310 given name.
311 """
312 return name in self.properties
313
315 "This class represents a <file> entry in the registry"
316 - def __init__(self, filename, type):
317 self.filename = filename
318 self.type = type
319
321 return os.path.basename(self.filename)
322
325
326 - def getFilename(self):
328
329 - def isType(self, type):
330 return self.type == type
331
333 "This class represents a <entry> entry in the registry"
334 - def __init__(self, type, location, function):
335 self.type = type
336 self.location = location
337 self.function = function
338
341
342 - def getLocation(self):
344
345 - def getModuleName(self, base=None):
346 if base:
347 path = os.path.join(base, self.getLocation())
348 else:
349 path = self.getLocation()
350 return common.pathToModuleName(path)
351
352 - def getFunction(self):
354
356 "This class represents a <eater> entry in the registry"
357 - def __init__(self, name, required=True, multiple=False):
358 self.name = name
359 self.required = required
360 self.multiple = multiple
361
364
365 - def getRequired(self):
367
368 - def getMultiple(self):
370
372 """
373 Registry parser
374
375 I have two modes, one to parse registries and another one to parse
376 standalone component files.
377
378 For parsing registries use the parseRegistry function and for components
379 use parseRegistryFile.
380
381 I also have a list of all components and directories which the
382 registry uses (instead of saving its own copy)
383 """
384
387
389 self._components = {}
390 self._directories = {}
391 self._bundles = {}
392 self._plugs = {}
393
395 return self._components.values()
396
403
405 return self._plugs.values()
406
413
415
416
417
418
419 components = {}
420 def addComponent(comp):
421 components[comp.getType()] = comp
422
423 parsers = {'component': (self._parseComponent, addComponent)}
424 self.parseFromTable(node, parsers)
425
426 return components
427
429
430
431
432
433
434
435
436
437
438
439 type, baseDir, description = self.parseAttributes(node,
440 required=('type', 'base'), optional=('description',))
441
442 files = []
443 source = fxml.Box(None)
444 entries = {}
445 eaters = []
446 feeders = []
447 synchronization = fxml.Box((False, 100))
448 sockets = []
449 properties = {}
450
451
452
453
454
455
456
457
458 parsers = {
459 'source': (self._parseSource, source.set),
460 'properties': (self._parseProperties, properties.update),
461 'files': (self._parseFiles, files.extend),
462 'entries': (self._parseEntries, entries.update),
463 'eater': (self._parseEater, eaters.append),
464 'feeder': (self._parseFeeder, feeders.append),
465 'synchronization': (self._parseSynchronization,
466 synchronization.set),
467 'sockets': (self._parseSockets, sockets.extend),
468 }
469
470 self.parseFromTable(node, parsers)
471
472 source = source.unbox()
473 needs_sync, clock_priority = synchronization.unbox()
474
475 return RegistryEntryComponent(self.filename,
476 type, source, description, baseDir,
477 properties, files,
478 entries, eaters, feeders,
479 needs_sync, clock_priority,
480 sockets)
481
486
488
489
490
491 attrs = self.parseAttributes(node, required=('name', 'type'),
492 optional=('required', 'multiple', 'description'))
493 name, type, required, multiple, description = attrs
494 required = common.strToBool(required)
495 multiple = common.strToBool(multiple)
496 return RegistryEntryProperty(name, type, description, required=required,
497 multiple=multiple)
498
515
516 parsers = {'property': (self._parseProperty, addProperty),
517 'compound-property': (self._parseCompoundProperty,
518 addProperty)}
519 self.parseFromTable(node, parsers)
520
521 return RegistryEntryCompoundProperty(name, description, properties,
522 required=required, multiple=multiple)
523
533
534 parsers = {'property': (self._parseProperty, addProperty),
535 'compound-property': (self._parseCompoundProperty,
536 addProperty)}
537
538 self.parseFromTable(node, parsers)
539
540 return properties
541
550
562
569
581
582 - def _parseEntry(self, node):
583 attrs = self.parseAttributes(node, ('type', 'location', 'function'))
584 type, location, function = attrs
585 return RegistryEntryEntry(type, location, function)
586
588
589
590
591
592
593 entries = {}
594 def addEntry(entry):
595 if entry.getType() in entries:
596 raise fxml.ParserError("entry %s already specified"
597 % entry.getType())
598 entries[entry.getType()] = entry
599
600 parsers = {'entry': (self._parseEntry, addEntry)}
601
602 self.parseFromTable(node, parsers)
603
604 return entries
605
615
620
628
629 - def _parsePlugEntry(self, node):
630
631
632
633 attrs = self.parseAttributes(node, ('location', 'function'))
634 location, function = attrs
635 return RegistryEntryEntry('plug', location, function)
636
638
639
640
641
642
643 type, socket = self.parseAttributes(node, ('type', 'socket'))
644
645 entry = fxml.Box(None)
646 properties = {}
647
648 parsers = {'entry': (self._parsePlugEntry, entry.set),
649 'properties': (self._parseProperties, properties.update)}
650
651 self.parseFromTable(node, parsers)
652
653 if not entry.unbox():
654 raise fxml.ParserError("<plug> %s needs an <entry>" % type)
655
656 return RegistryEntryPlug(self.filename, type,
657 socket, entry.unbox(), properties)
658
669
670 parsers = {'plug': (self._parsePlug, addPlug)}
671 self.parseFromTable(node, parsers)
672
673 return plugs
674
675
677 """
678 @param file: The file to parse, either as an open file object,
679 or as the name of a file to open.
680 @type file: str or file.
681 """
682 self.filename = getattr(file, 'name', '<string>')
683 root = self.getRoot(file)
684 node = root.documentElement
685
686 if node.nodeName != 'registry':
687
688
689 self.debug('%s does not have registry as root tag' % self.filename)
690 return
691
692
693 self._parseRoot(node, disallowed=['directories'])
694 root.unlink()
695
704
705 parsers = {'bundle': (self._parseBundle, addBundle)}
706 self.parseFromTable(node, parsers)
707
708 return bundles
709
711
712
713
714
715
716 attrs = self.parseAttributes(node, ('name',), ('project', 'under'))
717 name, project, under = attrs
718 project = project or 'flumotion'
719 under = under or 'pythondir'
720
721 dependencies = []
722 directories = []
723
724 parsers = {'dependencies': (self._parseBundleDependencies,
725 dependencies.extend),
726 'directories': (self._parseBundleDirectories,
727 directories.extend)}
728 self.parseFromTable(node, parsers)
729
730 return RegistryEntryBundle(name, project, under, dependencies, directories)
731
735
747
759
768
778
779 parsers = {'filename': (parseFilename, filenames.append)}
780 self.parseFromTable(node, parsers)
781
782 return RegistryEntryBundleDirectory(name, filenames)
783
784
786 """
787 @param file: The file to parse, either as an open file object,
788 or as the name of a file to open.
789 @type file: str or file.
790 """
791 self.filename = getattr(file, 'name', '<string>')
792 root = self.getRoot(file)
793 self._parseRoot(root.documentElement)
794 root.unlink()
795
797 return self._directories.values()
798
800 return self._directories[name]
801
803 """
804 Add a registry path object to the parser.
805
806 @type directory: {RegistryDirectory}
807 """
808 self._directories[directory.getPath()] = directory
809
811 """
812 Remove a directory from the parser given the path.
813 Used when the path does not actually contain any registry information.
814 """
815 if path in self._directories.keys():
816 del self._directories[path]
817
835
837
838
839
840
841 directories = {}
842 def addDirectory(d):
843 directories[d.getPath()] = d
844
845 parsers = {'directory': (self._parseDirectory, addDirectory)}
846 self.parseFromTable(node, parsers)
847
848 return directories
849
854
855
856
858 """
859 I represent a directory under a path managed by the registry.
860 I can be queried for a list of partial registry .xml files underneath
861 the given path, under the given prefix.
862 """
863 - def __init__(self, path, prefix='flumotion'):
864 self._path = path
865 self._prefix = prefix
866 scanPath = os.path.join(path, prefix)
867 self._files, self._dirs = self._getFileLists(scanPath)
868
870 return "<RegistryDirectory %s>" % self._path
871
873 """
874 Get all files ending in .xml from all directories under the given root.
875
876 @type root: string
877 @param root: the root directory under which to search
878
879 @returns: a list of .xml files, relative to the given root directory
880 """
881 files = []
882 dirs = []
883
884 if os.path.exists(root):
885 try:
886 directory_files = os.listdir(root)
887 except OSError, e:
888 if e.errno == errno.EACCES:
889 return files, dirs
890 else:
891 raise
892
893 dirs.append(root)
894
895 for dir in directory_files:
896 filename = os.path.join(root, dir)
897
898 if not os.path.isdir(filename):
899 if filename.endswith('.xml'):
900 files.append(filename)
901
902
903 elif dir != '.svn':
904 newFiles, newDirs = self._getFileLists(filename)
905 files.extend(newFiles)
906 dirs.extend(newDirs)
907
908 return files, dirs
909
911 def _rebuildNeeded(file):
912 try:
913 if _getMTime(file) > mtime:
914 self.debug("Path %s changed since registry last "
915 "scanned", f)
916 return True
917 return False
918 except OSError:
919 self.debug("Failed to stat file %s, need to rescan", f)
920 return True
921
922 assert self._files, "Path %s does not have registry files" % self._path
923 for f in self._files:
924 if _rebuildNeeded(f):
925 return True
926 for f in self._dirs:
927 if _rebuildNeeded(f):
928 return True
929 return False
930
932 """
933 Return a list of all .xml registry files underneath this registry
934 path.
935 """
936 return self._files
937
940
942 - def __init__(self, components, plugs, bundles, directories):
943 """
944 @param components: components to write
945 @type components: list of L{RegistryEntryComponent}
946 @param plugs: plugs to write
947 @type plugs: list of L{RegistryEntryPlug}
948 @param bundles: bundles to write
949 @type bundles: list of L{RegistryEntryBundle}
950 @param directories: directories to write
951 @type directories: list of L{RegistryEntryBundleDirectory}
952 """
953 self.components = components
954 self.plugs = plugs
955 self.bundles = bundles
956 self.directories = directories
957
958 - def dump(self, fd):
959 """
960 Dump the cache of components to the given opened file descriptor.
961
962 @type fd: integer
963 @param fd: open file descriptor to write to
964 """
965
966 def w(i, msg):
967 print >> fd, ' '*i + msg
968 def e(attr):
969 return saxutils.quoteattr(attr)
970
971 def _dump_proplist(i, proplist, ioff=2):
972 for prop in proplist:
973 if isinstance(prop, RegistryEntryCompoundProperty):
974 _dump_compound(i, prop)
975 else:
976 w(i, ('<property name="%s" type="%s"'
977 % (prop.getName(), prop.getType())))
978 w(i, (' description=%s'
979 % (e(prop.getDescription()),)))
980 w(i, (' required="%s" multiple="%s"/>'
981 % (prop.isRequired(), prop.isMultiple())))
982
983 def _dump_compound(i, cprop, ioff=2):
984 w(i, ('<compound-property name="%s"' % (cprop.getName(),)))
985 w(i, (' description=%s'
986 % (e(cprop.getDescription()),)))
987 w(i, (' required="%s" multiple="%s">'
988 % (cprop.isRequired(), cprop.isMultiple())))
989 _dump_proplist(i + ioff, cprop.getProperties())
990 w(i, ('</compound-property>'))
991
992 w(0, '<registry>')
993 w(0, '')
994
995
996 w(2, '<components>')
997 w(0, '')
998 for component in self.components:
999 w(4, '<component type="%s" base="%s"' % (
1000 component.getType(), component.getBase()))
1001 w(4, ' description=%s>'
1002 % (e(component.getDescription()),))
1003
1004 w(6, '<source location="%s"/>' % component.getSource())
1005 for x in component.getEaters():
1006 w(6, '<eater name="%s" required="%s" multiple="%s"/>'
1007 % (x.getName(), x.getRequired() and "yes" or "no",
1008 x.getMultiple() and "yes" or "no"))
1009 for x in component.getFeeders():
1010 w(6, '<feeder name="%s"/>' % x)
1011 w(6, '<synchronization required="%s" clock-priority="%d"/>'
1012 % (component.getNeedsSynchronization() and "yes" or "no",
1013 component.getClockPriority()))
1014
1015 sockets = component.getSockets()
1016 if sockets:
1017 w(6, '<sockets>')
1018 for socket in sockets:
1019 w(8, '<socket type="%s"/>' % socket)
1020 w(6, '</sockets>')
1021
1022 w(6, '<properties>')
1023 _dump_proplist(8, component.getProperties())
1024 w(6, '</properties>')
1025
1026 files = component.getFiles()
1027 if files:
1028 w(6, '<files>')
1029 for file in files:
1030 w(8, '<file name="%s" type="%s"/>' % (
1031 file.getName(),
1032 file.getType()))
1033 w(6, '</files>')
1034
1035 entries = component.getEntries()
1036 if entries:
1037 w(6, '<entries>')
1038 for entry in entries:
1039 w(8, '<entry type="%s" location="%s" function="%s"/>' % (
1040 entry.getType(),
1041 entry.getLocation(),
1042 entry.getFunction()))
1043 w(6, '</entries>')
1044 w(4, '</component>')
1045 w(0, '')
1046
1047 w(2, '</components>')
1048 w(0, '')
1049
1050
1051 w(2, '<plugs>')
1052 w(0, '')
1053 for plug in self.plugs:
1054 w(4, '<plug type="%s" socket="%s">'
1055 % (plug.getType(), plug.getSocket()))
1056
1057 entry = plug.getEntry()
1058 w(6, ('<entry location="%s" function="%s"/>'
1059 % (entry.getLocation(), entry.getFunction())))
1060
1061 w(6, '<properties>')
1062 _dump_proplist(8, plug.getProperties())
1063 w(6, '</properties>')
1064
1065 w(4, '</plug>')
1066 w(0, '')
1067
1068 w(2, '</plugs>')
1069 w(0, '')
1070
1071
1072 w(2, '<bundles>')
1073 for bundle in self.bundles:
1074 w(4, '<bundle name="%s" under="%s" project="%s">' % (
1075 bundle.getName(), bundle.getUnder(), bundle.getProject()))
1076
1077 dependencies = bundle.getDependencies()
1078 if dependencies:
1079 w(6, '<dependencies>')
1080 for dependency in dependencies:
1081 w(8, '<dependency name="%s"/>' % dependency)
1082 w(6, '</dependencies>')
1083
1084 dirs = bundle.getDirectories()
1085 if dirs:
1086 w(6, '<directories>')
1087 for dir in dirs:
1088 w(8, '<directory name="%s">' % dir.getName())
1089 for filename in dir.getFiles():
1090 w(10, '<filename location="%s" relative="%s"/>' % (
1091 filename.getLocation(), filename.getRelative()))
1092 w(8, '</directory>')
1093 w(6, '</directories>')
1094
1095 w(4, '</bundle>')
1096 w(0, '')
1097 w(2, '</bundles>')
1098
1099
1100
1101 directories = self.directories
1102 if directories:
1103 w(2, '<directories>')
1104 w(0, '')
1105 for d in directories:
1106 w(4, '<directory filename="%s"/>' % d.getPath())
1107 w(2, '</directories>')
1108 w(0, '')
1109
1110 w(0, '</registry>')
1111
1113 """Registry, this is normally not instantiated."""
1114
1115 logCategory = 'registry'
1116 filename = os.path.join(configure.registrydir, 'registry.xml')
1117
1136
1138 """
1139 @param file: The file to add, either as an open file object, or
1140 as the name of a file to open.
1141 @type file: str or file.
1142 """
1143 if isinstance(file, str) and file.endswith('registry.xml'):
1144 self.warning('%s seems to be an old registry in your tree, '
1145 'please remove it', file)
1146 self.debug('Adding file: %r', file)
1147 self._parser.parseRegistryFile(file)
1148
1150 f = StringIO(string)
1151 self.addFile(f)
1152 f.close()
1153
1155 """
1156 Add a registry path to this registry, scanning it for registry
1157 snippets.
1158
1159 @param path: a full path containing a 'flumotion' directory,
1160 which will be scanned for registry files.
1161
1162 @rtype: bool
1163 @returns: whether the path could be added
1164 """
1165 self.debug('path %s, prefix %s' % (path, prefix))
1166 if not os.path.exists(path):
1167 self.warning("Cannot add non-existent path '%s' to registry" % path)
1168 return False
1169 if not os.path.exists(os.path.join(path, prefix)):
1170 self.warning("Cannot add path '%s' to registry "
1171 "since it does not contain prefix '%s'" % (path, prefix))
1172 return False
1173
1174
1175
1176 self.info('Scanning registry path %s' % path)
1177 registryPath = RegistryDirectory(path, prefix=prefix)
1178 files = registryPath.getFiles()
1179 self.debug('Found %d possible registry files' % len(files))
1180 map(self.addFile, files)
1181
1182 self._parser.addDirectory(registryPath)
1183 return True
1184
1185
1186
1188 return len(self._parser._components) == 0
1189
1191 """
1192 @rtype: L{RegistryEntryComponent}
1193 """
1194 return self._parser.getComponent(name)
1195
1197 return name in self._parser._components
1198
1201
1203 """
1204 @rtype: L{RegistryEntryPlug}
1205 """
1206 return self._parser.getPlug(type)
1207
1209 return name in self._parser._plugs
1210
1213
1215 return self._parser._bundles.values()
1216
1219
1221 """
1222 @rtype: L{flumotion.common.bundle.BundlerBasket}
1223 """
1224 def load():
1225 ret = bundle.BundlerBasket()
1226 for b in self.getBundles():
1227 bundleName = b.getName()
1228 self.debug('Adding bundle %s' % bundleName)
1229 for d in b.getDirectories():
1230 directory = d.getName()
1231 for file in d.getFiles():
1232 try:
1233 basedir = b.getBaseDir()
1234 except errors.NoProjectError, e:
1235 self.warning("Could not find project %s" % e.args)
1236 raise
1237 fullpath = os.path.join(basedir, directory,
1238 file.getLocation())
1239 relative = file.getRelative()
1240 self.log('Adding path %s as %s to bundle %s' % (
1241 fullpath, relative, bundleName))
1242 try:
1243 ret.add(bundleName, fullpath, relative)
1244 except Exception, e:
1245 self.debug("Reason: %r" % e)
1246 raise RuntimeError(
1247 'Could not add %s to bundle %s (%s)'
1248 % (fullpath, bundleName, e))
1249 for d in b.getDependencies():
1250 self.log('Adding dependency of %s on %s' % (bundleName, d))
1251 ret.depend(bundleName, d)
1252 return ret
1253
1254 try:
1255 return load()
1256 except Exception, e:
1257 self.warning("Bundle problem, rebuilding registry (%s)" % e)
1258 self.verify(force=True)
1259 try:
1260 return load()
1261 except Exception, e:
1262 self.debug("Could not register bundles twice: %s" %
1263 log.getExceptionMessage(e))
1264 self.error("Could not not register bundles (%s)" % e)
1265
1266 - def dump(self, fd):
1276
1278 """
1279 Clean the cache of components.
1280 """
1281 self._parser.clean()
1282
1284 if not os.path.exists(self.filename):
1285 return True
1286
1287
1288
1289 registryPaths = sets.Set(self._getRegistryPathsFromEnviron())
1290 oldRegistryPaths = sets.Set([dir.getPath()
1291 for dir in self.getDirectories()])
1292 if registryPaths != oldRegistryPaths:
1293 if oldRegistryPaths - registryPaths:
1294 return True
1295 if filter(os.path.exists, registryPaths - oldRegistryPaths):
1296 return True
1297
1298 registry_modified = _getMTime(self.filename)
1299 for d in self._parser.getDirectories():
1300 if d.rebuildNeeded(registry_modified):
1301 return True
1302
1303 return False
1304
1305 - def save(self, force=False):
1306 if not force and not self.rebuildNeeded():
1307 return
1308
1309 self.info('Saving registry to %s' % self.filename)
1310
1311
1312 dir = os.path.split(self.filename)[0]
1313 if not os.path.exists(dir):
1314 try:
1315 os.makedirs(dir)
1316 except OSError, e:
1317 if e.errno == errno.EACCES:
1318 self.error('Registry directory %s could not be created !' %
1319 dir)
1320 else:
1321 raise
1322
1323 if not os.path.isdir(dir):
1324 self.error('Registry directory %s is not a directory !')
1325 try:
1326 fd = open(self.filename, 'w')
1327 self.dump(fd)
1328 except IOError, e:
1329 if e.errno == errno.EACCES:
1330 self.error('Registry file %s could not be created !' %
1331 self.filename)
1332 else:
1333 raise
1334
1336 registryPaths = [configure.pythondir, ]
1337 if os.environ.has_key('FLU_PROJECT_PATH'):
1338 paths = os.environ['FLU_PROJECT_PATH']
1339 registryPaths += paths.split(':')
1340 return registryPaths
1341
1342 - def verify(self, force=False):
1356
1358 - def __init__(self, fromRegistry=None, onlyBundles=None):
1359 """
1360 @param fromRegistry: The registry to subset, or the default.
1361 @type fromRegistry: L{ComponentRegistry}
1362 @param onlyBundles: If given, only include the subset of the
1363 registry that is provided by bundles whose names are in this
1364 list.
1365 @type onlyBundles: list of str
1366 """
1367 self.fromRegistry = fromRegistry
1368 self.onlyBundles = onlyBundles
1369
1370 - def dump(self, fd):
1386
1387 pred = lambda c: (filter(lambda f: fileIsBundled(c.getBase(),
1388 f.getFilename()),
1389 c.getFiles())
1390 or filter(lambda e: fileIsBundled(c.getBase(),
1391 e.getLocation()),
1392 c.getEntries()))
1393 components = filter(pred, reg.getComponents())
1394
1395 pred = lambda p: p.getEntry().getLocation() in bundledfiles
1396 plugs = filter(pred, reg.getPlugs())
1397
1398 directories = []
1399
1400 regwriter = RegistryWriter(components, plugs, bundles, directories)
1401 regwriter.dump(fd)
1402
1403 __registry = None
1404
1418