def _toposort_file(filename, key_pairs): """ filename: the csv file to sort key_pairs: tuples of the form (parent, child) where for each line in the file the line[parent] needs to be sorted before any of the line[child]. parent is usually the name of the foreign_key column and child is usually the column that the foreign key points to, e.g ('parent_id', 'id') """ f = open(filename, 'rb') reader = UnicodeReader(f, quotechar=QUOTE_CHAR, quoting=QUOTE_STYLE) # create a dictionary of the lines mapped to the child field bychild = {} for line in reader: for parent, child in key_pairs: bychild[line[child]] = line f.close() fields = reader.reader.fieldnames del reader # create pairs from the values in the lines where pair[0] # should come before pair[1] when the lines are sorted pairs = [] for line in bychild.values(): for parent, child in key_pairs: if line[parent] and line[child]: pairs.append((line[parent], line[child])) # sort the keys and flatten the lines back into a list sorted_keys = utils.topological_sort(bychild.keys(), pairs) sorted_lines = [] for key in sorted_keys: sorted_lines.append(bychild[key]) # write a temporary file of the sorted lines import tempfile tmppath = tempfile.mkdtemp() head, tail = os.path.split(filename) filename = os.path.join(tmppath, tail) tmpfile = open(filename, 'wb') tmpfile.write('%s\n' % ','.join(fields)) #writer = UnicodeWriter(tmpfile, fields, quotechar=QUOTE_CHAR, writer = csv.DictWriter(tmpfile, fields, quotechar=QUOTE_CHAR, quoting=QUOTE_STYLE) writer.writerows(sorted_lines) tmpfile.flush() tmpfile.close() del writer return filename
def install(plugins_to_install, import_defaults=True, force=False): """ :param plugins_to_install: A list of plugins to install. If the string "all" is passed then install all plugins listed in the bauble.pluginmgr.plugins dict that aren't already listed in the plugin registry. :param import_defaults: Flag passed to the plugin's install() method to indicate whether it should import its default data. :type import_defaults: bool :param force: Force, don't ask questions. :type force: book """ logger.debug('pluginmgr.install(%s)' % str(plugins_to_install)) if plugins_to_install is 'all': to_install = plugins.values() else: to_install = plugins_to_install if len(to_install) == 0: # no plugins to install return # sort the plugins by their dependency depends, unmet = _create_dependency_pairs(to_install) if unmet != {}: logger.debug(unmet) raise BaubleError('unmet dependencies') to_install = utils.topological_sort(to_install, depends) if not to_install: raise BaubleError( _('The plugins contain a dependency loop. This ' 'can happend if two plugins directly or ' 'indirectly rely on each other')) try: for p in to_install: logger.debug('install: %s' % p) p.install(import_defaults=import_defaults) # issue #28: here we make sure we don't add the plugin to the # registry twice but we should really update the version number # in the future when we accept versioned plugins (if ever) if not PluginRegistry.exists(p): PluginRegistry.add(p) except Exception, e: logger.warning('bauble.pluginmgr.install(): %s' % utils.utf8(e)) raise
def install(plugins_to_install, import_defaults=True, force=False): """ :param plugins_to_install: A list of plugins to install. If the string "all" is passed then install all plugins listed in the bauble.pluginmgr.plugins dict that aren't already listed in the plugin registry. :param import_defaults: Flag passed to the plugin's install() method to indicate whether it should import its default data. :type import_defaults: bool :param force: Force, don't ask questions. :type force: book """ logger.debug('pluginmgr.install(%s)' % str(plugins_to_install)) if plugins_to_install is 'all': to_install = plugins.values() else: to_install = plugins_to_install if len(to_install) == 0: # no plugins to install return # sort the plugins by their dependency depends, unmet = _create_dependency_pairs(to_install) if unmet != {}: logger.debug(unmet) raise BaubleError('unmet dependencies') to_install = utils.topological_sort(to_install, depends) if not to_install: raise BaubleError(_('The plugins contain a dependency loop. This ' 'can happend if two plugins directly or ' 'indirectly rely on each other')) try: for p in to_install: logger.debug('install: %s' % p) p.install(import_defaults=import_defaults) # issue #28: here we make sure we don't add the plugin to the # registry twice but we should really update the version number # in the future when we accept versioned plugins (if ever) if not PluginRegistry.exists(p): PluginRegistry.add(p) except Exception, e: logger.warning('bauble.pluginmgr.install(): %s' % utils.utf8(e)) raise
def test_topological_sort_loop(self): self.assertEqual(utils.topological_sort([1,2], [(2,1), (1,2)]), None)
def test_topological_sort_partial(self): self.assertEqual(utils.topological_sort([1,2,3,4], [(2,1)]), [4, 3, 2, 1])
def test_topological_sort_total(self): self.assertEqual(utils.topological_sort([1,2,3], [(2,1), (3,2)]), [3, 2, 1])
if not_registered: msg = _('The following plugins are in the registry but ' 'could not be loaded:\n\n%(plugins)s') % \ {'plugins': utils.utf8(', '.join(sorted(not_registered)))} utils.message_dialog(utils.xml_safe(msg), type=gtk.MESSAGE_WARNING) except Exception, e: logger.warning('unhandled exception %s' % e) raise if not registered: # no plugins to initialize return deps, unmet = _create_dependency_pairs(registered) ordered = utils.topological_sort(registered, deps) if not ordered: raise BaubleError(_('The plugins contain a dependency loop. This ' 'can happen if two plugins directly or ' 'indirectly rely on each other')) # call init() for each ofthe plugins for plugin in ordered: logger.debug('about to invoke init on: %s' % plugin) try: plugin.init() logger.debug('plugin %s initialized' % plugin) except KeyError, e: # keep the plugin in the registry so if we find it again we do # not offer the user the option to reinstall it, something which # could overwrite data
def install(plugins_to_install, import_defaults=True, force=False): """ :param plugins_to_install: A list of plugins to install. If the string "all" is passed then install all plugins listed in the bauble.pluginmgr.plugins dict that aren't already listed in the plugin registry. :param import_defaults: Flag passed to the plugin's install() method to indicate whether it should import its default data. :type import_defaults: bool :param force: Force, don't ask questions. :type force: book """ #debug('pluginmgr.install(%s)' % plugins_to_install) if plugins_to_install is 'all': to_install = plugins.values() else: to_install = plugins_to_install if len(to_install) == 0: # no plugins to install return # sort the plugins by their dependency depends, unmet = _create_dependency_pairs(to_install) if unmet != {}: debug(unmet) raise BaubleError('unmet dependencies') to_install = utils.topological_sort(to_install, depends) if not to_install: raise BaubleError(_('The plugins contain a dependency loop. This '\ 'can happend if two plugins directly or '\ 'indirectly rely on each other')) # msg = _('The %(plugin)s plugin depends on the %(other_plugin)s '\ # 'plugin but the %(other_plugin)s plugin wasn\'t found.') \ # % {'plugin': e.plugin.__name__, 'other_plugin': e.not_found} # utils.message_dialog(msg, gtk.MESSAGE_WARNING) # to_install = topological_sort(to_install, depends) # except DependencyError, e: # msg = _('The %(plugin)s plugin depends on the %(other_plugin)s '\ # 'plugin but the %(other_plugin)s plugin wasn\'t found.') \ # % {'plugin': e.plugin.__name__, 'other_plugin': e.not_found} # utils.message_dialog(msg, gtk.MESSAGE_WARNING) # raise # except DependencyError, e: # error(utils.utf8(e)) try: for p in to_install: #debug('install: %s' % p.__name__) p.install(import_defaults=import_defaults) # TODO: here we make sure we don't add the plugin to the # registry twice but we should really update the version # number in the future when we accept versioned plugins # (if ever) if not PluginRegistry.exists(p): PluginRegistry.add(p) #session.commit() except Exception, e: warning('bauble.pluginmgr.install(): %s' % utils.utf8(e)) raise
def test_topological_sort_loop(self): self.assertEqual(utils.topological_sort([1, 2], [(2, 1), (1, 2)]), None)
def test_topological_sort_partial(self): self.assertEqual(utils.topological_sort([1, 2, 3, 4], [(2, 1)]), [4, 3, 2, 1])
def test_topological_sort_total(self): self.assertEqual(utils.topological_sort([1, 2, 3], [(2, 1), (3, 2)]), [3, 2, 1])