def i18n_locale(locale_name): """ Retrieve a locale in a Jed-compatible format """ config = Config.getInstance() root_path = os.path.join(current_app.root_path, 'translations') plugin_key = ','.join(sorted(plugin_engine.get_active_plugins())) cache_file = os.path.join(config.getXMLCacheDir(), 'assets_i18n_{}_{}.js'.format(locale_name, crc32(plugin_key))) if not os.path.exists(cache_file): i18n_data = locale_data(root_path, locale_name, 'indico') if not i18n_data: # Dummy data, not having the indico domain would cause lots of failures i18n_data = {'indico': {'': {'domain': 'indico', 'lang': locale_name}}} for pid, plugin in plugin_engine.get_active_plugins().iteritems(): data = {} if plugin.translation_path: data = locale_data(plugin.translation_path, locale_name, pid) if not data: # Dummy entry so we can still load the domain data = {pid: {'': {'domain': pid, 'lang': locale_name}}} i18n_data.update(data) if not i18n_data: raise NotFound("Translation for language '{}' not found".format(locale_name)) with open(cache_file, 'wb') as f: f.write("window.TRANSLATIONS = {};".format(json.dumps(i18n_data))) return send_file('{}.js'.format(locale_name), cache_file, mimetype='application/x-javascript', no_cache=False, conditional=True)
def __call__(self, app=None, *args, **kwargs): PluginScriptDirectory.dir = os.path.join(app.root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory with app.app_context(): active_plugins = plugin_engine.get_active_plugins() plugins = set(kwargs.pop('plugins')) if plugins: invalid_plugins = plugins - active_plugins.viewkeys() if invalid_plugins: print cformat( '%{red!}Invalid plugin(s) specified: {}').format( ', '.join(invalid_plugins)) sys.exit(1) for plugin in active_plugins.itervalues(): if plugins and plugin.name not in plugins: continue if not os.path.exists(plugin.alembic_versions_path): print cformat( "%{cyan}skipping plugin '{}' (no migrations folder)" ).format(plugin.name) continue print cformat( "%{cyan!}executing command for plugin '{}'").format( plugin.name) with plugin.plugin_context(): super(PluginDBCommand, self).__call__(app, *args, **kwargs)
def prepare(): """Initializes an empty database (creates tables, sets alembic rev to HEAD)""" tables = get_all_tables(db) if 'alembic_version' not in tables['public']: print colored('Setting the alembic version to HEAD', 'green') stamp() PluginScriptDirectory.dir = os.path.join(current_app.root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory plugin_msg = cformat("%{cyan}Setting the alembic version of the %{cyan!}{}%{reset}%{cyan} " "plugin to HEAD%{reset}") for plugin in plugin_engine.get_active_plugins().itervalues(): if not os.path.exists(plugin.alembic_versions_path): continue print plugin_msg.format(plugin.name) with plugin.plugin_context(): stamp() # Retrieve the table list again, just in case we created unexpected hables tables = get_all_tables(db) tables['public'] = [t for t in tables['public'] if not t.startswith('alembic_version')] if any(tables.viewvalues()): print colored('Your database is not empty!', 'red') print colored('If you just added a new table/model, create an alembic revision instead!', 'yellow') print print 'Tables in your database:' for schema, schema_tables in sorted(tables.items()): for t in schema_tables: print cformat(' * %{cyan}{}%{reset}.%{cyan!}{}%{reset}').format(schema, t) return if not _require_extensions('unaccent', 'pg_trgm'): return print colored('Creating tables', 'green') db.create_all()
def get_payment_plugins(): """Return a dict containing the available payment plugins.""" return { remove_prefix_re.sub('', p.name): p for p in plugin_engine.get_active_plugins().values() if isinstance(p, PaymentPluginMixin) }
def _get_sql_line(): indico_path = current_app.root_path makac_path = os.path.abspath(os.path.join(indico_path, "..", "MaKaC")) paths = [indico_path, makac_path] + [p.root_path for p in plugin_engine.get_active_plugins().itervalues()] stack = [item for item in reversed(traceback.extract_stack()) if _interesting_tb_item(item, paths)] for i, item in enumerate(stack): return {"file": item[0], "line": item[1], "function": item[2], "items": stack[i : i + 5]}
def _make_shell_context(): context = {} info = [cformat('%{white!}Available objects')] add_to_context = partial(_add_to_context, context, info) add_to_context_multi = partial(_add_to_context_multi, context, info) add_to_context_smart = partial(_add_to_context_smart, context, info) # Common stdlib modules info.append(cformat('*** %{magenta!}stdlib%{reset} ***')) DATETIME_ATTRS = ('date', 'time', 'datetime', 'timedelta') ORM_ATTRS = ('joinedload', 'defaultload', 'contains_eager', 'lazyload', 'noload', 'subqueryload', 'undefer', 'undefer_group', 'load_only') add_to_context_multi([getattr(datetime, attr) for attr in DATETIME_ATTRS] + [getattr(sqlalchemy.orm, attr) for attr in ORM_ATTRS] + [itertools, re, sys, os], color='yellow') # Models info.append(cformat('*** %{magenta!}Models%{reset} ***')) models = [ cls for name, cls in sorted(db.Model._decl_class_registry.items(), key=itemgetter(0)) if hasattr(cls, '__table__') ] add_to_context_smart(models) # Tasks info.append(cformat('*** %{magenta!}Tasks%{reset} ***')) tasks = [ task for task in sorted(celery.tasks.values()) if not task.name.startswith('celery.') ] add_to_context_smart(tasks, get_name=lambda x: x.name.replace('.', '_'), color='blue!') # Plugins info.append(cformat('*** %{magenta!}Plugins%{reset} ***')) plugins = [ type(plugin) for plugin in sorted(plugin_engine.get_active_plugins().values(), key=attrgetter('name')) ] add_to_context_multi(plugins, color='yellow!') # Utils info.append(cformat('*** %{magenta!}Misc%{reset} ***')) add_to_context(celery, 'celery', doc='celery app', color='blue!') add_to_context(db, 'db', doc='sqlalchemy db interface', color='cyan!') add_to_context(now_utc, 'now_utc', doc='get current utc time', color='cyan!') add_to_context(config, 'config', doc='indico config') add_to_context(current_app, 'app', doc='flask app') add_to_context(lambda *a, **kw: server_to_utc(datetime.datetime(*a, **kw)), 'dt', doc='like datetime() but converted from localtime to utc') add_to_context(Event.get, 'EE', doc='get event by id') # Stuff from plugins signals.plugin.shell_context.send( add_to_context=add_to_context, add_to_context_multi=add_to_context_multi) return context, info
def i18n_locale(locale_name): """ Retrieve a locale in a Jed-compatible format """ root_path = os.path.join(current_app.root_path, 'translations') cache_file = os.path.join(config.CACHE_DIR, 'assets_i18n_{}_{}_{}.js'.format( locale_name, indico.__version__, config.hash)) if not os.path.exists(cache_file): i18n_data = locale_data(root_path, locale_name, 'indico') if not i18n_data: # Dummy data, not having the indico domain would cause lots of failures i18n_data = {'indico': {'': {'domain': 'indico', 'lang': locale_name}}} for pid, plugin in plugin_engine.get_active_plugins().iteritems(): data = {} if plugin.translation_path: data = locale_data(plugin.translation_path, locale_name, pid) if not data: # Dummy entry so we can still load the domain data = {pid: {'': {'domain': pid, 'lang': locale_name}}} i18n_data.update(data) with open(cache_file, 'wb') as f: f.write("window.TRANSLATIONS = {};".format(json.dumps(i18n_data))) return send_file('{}.js'.format(locale_name), cache_file, mimetype='application/javascript', no_cache=False, conditional=True)
def _call_with_plugins(*args, **kwargs): func = kwargs.pop('_func') ctx = click.get_current_context() all_plugins = ctx.parent.params['all_plugins'] plugin = ctx.parent.params['plugin'] if plugin: plugins = {plugin_engine.get_plugin(plugin)} elif all_plugins: plugins = set(plugin_engine.get_active_plugins().viewvalues()) else: plugins = None if plugins is None: func(*args, **kwargs) else: PluginScriptDirectory.dir = os.path.join(current_app.root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory for plugin in plugins: if not os.path.exists(plugin.alembic_versions_path): print cformat( "%{cyan}skipping plugin '{}' (no migrations folder)" ).format(plugin.name) continue print cformat("%{cyan!}executing command for plugin '{}'").format( plugin.name) with plugin.plugin_context(): func(*args, **kwargs)
def get_payment_plugins(): """Returns a dict containing the available payment plugins.""" return { remove_prefix_re.sub("", p.name): p for p in plugin_engine.get_active_plugins().itervalues() if isinstance(p, PaymentPluginMixin) }
def _get_sql_line(): paths = [current_app.root_path] + [p.root_path for p in plugin_engine.get_active_plugins().values()] stack = [item for item in reversed(traceback.extract_stack()) if _interesting_tb_item(item, paths)] for i, item in enumerate(stack): return {'file': item[0], 'line': item[1], 'function': item[2], 'items': [_frame_to_tuple(frame) for frame in stack[i:i+5]]}
def get_vc_plugins(): """Return a dict containing the available videoconference plugins.""" from indico.modules.vc import VCPluginMixin return { p.service_name: p for p in plugin_engine.get_active_plugins().values() if isinstance(p, VCPluginMixin) }
def _get_sql_line(): paths = [current_app.root_path] + [p.root_path for p in plugin_engine.get_active_plugins().itervalues()] stack = [item for item in reversed(traceback.extract_stack()) if _interesting_tb_item(item, paths)] for i, item in enumerate(stack): return {'file': item[0], 'line': item[1], 'function': item[2], 'items': stack[i:i+5]}
def _get_sql_line(): indico_path = current_app.root_path makac_path = os.path.abspath(os.path.join(indico_path, '..', 'MaKaC')) paths = [indico_path, makac_path] + [p.root_path for p in plugin_engine.get_active_plugins().itervalues()] stack = [item for item in reversed(traceback.extract_stack()) if _interesting_tb_item(item, paths)] for i, item in enumerate(stack): return {'file': item[0], 'line': item[1], 'function': item[2], 'items': stack[i:i+5]}
def menu_entries_for_event(event): from indico.core.plugins import plugin_engine custom_menu_enabled = layout_settings.get(event, "use_custom_menu") entries = MenuEntry.get_for_event(event) if custom_menu_enabled else [] signal_entries = get_menu_entries_from_signal() cache_key = unicode(event.id) plugin_hash = binascii.crc32(",".join(sorted(plugin_engine.get_active_plugins()))) & 0xFFFFFFFF cache_version = "{}:{}".format(MaKaC.__version__, plugin_hash) processed = entries and _cache.get(cache_key) == cache_version if not processed: # menu entries from signal pos_gen = count(start=(entries[-1].position + 1) if entries else 0) entry_names = {entry.name for entry in entries} # Keeping only new entries from the signal new_entry_names = signal_entries.viewkeys() - entry_names # Mapping children data to their parent children = defaultdict(list) for name, data in signal_entries.iteritems(): if name in new_entry_names and data.parent is not None: children[data.parent].append(data) # Building the entries new_entries = [ _build_menu_entry(event, custom_menu_enabled, data, next(pos_gen), children=children.get(data.name)) for (name, data) in sorted(signal_entries.iteritems(), key=lambda (name, data): _menu_entry_key(data)) if name in new_entry_names and data.parent is None ] if custom_menu_enabled: with db.tmp_session() as sess: sess.add_all(new_entries) try: sess.commit() except IntegrityError as e: # If there are two parallel requests trying to insert a new menu # item one of them will fail with an error due to the unique index. # If the IntegrityError involves that index, we assume it's just the # race condition and ignore it. sess.rollback() if "ix_uq_menu_entries_event_id_name" not in unicode(e.message): raise else: _cache.set(cache_key, cache_version) entries = MenuEntry.get_for_event(event) else: entries = new_entries return entries
def get_context(self): if self._context is None: self._context = context = {} self._info = [] add_to_context = partial(_add_to_context, context, self._info) add_to_context_multi = partial(_add_to_context_multi, context, self._info) add_to_context_smart = partial(_add_to_context_smart, context, self._info) # Common stdlib modules self._info.append(cformat('*** %{magenta!}stdlib%{reset} ***')) DATETIME_ATTRS = ('date', 'time', 'datetime', 'timedelta') ORM_ATTRS = ('joinedload', 'defaultload', 'contains_eager', 'lazyload', 'noload', 'subqueryload', 'undefer', 'undefer_group', 'load_only') add_to_context_multi([getattr(datetime, attr) for attr in DATETIME_ATTRS] + [getattr(sqlalchemy.orm, attr) for attr in ORM_ATTRS] + [itertools, re, sys, os], color='yellow') # Legacy Indico self._info.append(cformat('*** %{magenta!}Legacy%{reset} ***')) add_to_context_multi([Conference, ConferenceHolder], color='green') add_to_context(LocalProxy(HelperMaKaCInfo.getMaKaCInfoInstance), 'minfo', color='green') # Models self._info.append(cformat('*** %{magenta!}Models%{reset} ***')) models = [cls for name, cls in sorted(db.Model._decl_class_registry.items(), key=itemgetter(0)) if hasattr(cls, '__table__')] add_to_context_smart(models) # Tasks self._info.append(cformat('*** %{magenta!}Tasks%{reset} ***')) tasks = [task for task in sorted(celery.tasks.values()) if not task.name.startswith('celery.')] add_to_context_smart(tasks, get_name=lambda x: x.name.replace('.', '_'), color='blue!') # Plugins self._info.append(cformat('*** %{magenta!}Plugins%{reset} ***')) plugins = [type(plugin) for plugin in sorted(plugin_engine.get_active_plugins().values(), key=attrgetter('name'))] add_to_context_multi(plugins, color='yellow!') # Utils self._info.append(cformat('*** %{magenta!}Misc%{reset} ***')) add_to_context(celery, 'celery', doc='celery app', color='blue!') add_to_context(DBMgr.getInstance(), 'dbi', doc='zodb db interface', color='cyan!') add_to_context(db, 'db', doc='sqlalchemy db interface', color='cyan!') add_to_context(transaction, doc='transaction module', color='cyan!') add_to_context(now_utc, 'now_utc', doc='get current utc time', color='cyan!') add_to_context(IndicoConfigWrapper(Config.getInstance()), 'config', doc='indico config') add_to_context(current_app, 'app', doc='flask app') add_to_context(lambda *a, **kw: server_to_utc(datetime.datetime(*a, **kw)), 'dt', doc='like datetime() but converted from localtime to utc') add_to_context(lambda x: ConferenceHolder().getById(x, True), 'E', doc='get event by id (Conference)') add_to_context(Event.get, 'EE', doc='get event by id (Event)') # Stuff from plugins signals.plugin.shell_context.send(add_to_context=add_to_context, add_to_context_multi=add_to_context_multi) return self._context
def prepare_db(empty=False, root_path=None, verbose=True): """Initialize an empty database (create tables, set alembic rev to HEAD).""" if not _require_pg_version('9.6'): return if not _require_encoding('UTF8'): return if not _require_extensions('unaccent', 'pg_trgm'): return root_path = root_path or current_app.root_path tables = get_all_tables(db) if 'alembic_version' not in tables['public']: if verbose: print(cformat('%{green}Setting the alembic version to HEAD')) stamp(directory=os.path.join(root_path, 'migrations'), revision='heads') PluginScriptDirectory.dir = os.path.join(root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory plugin_msg = cformat( "%{cyan}Setting the alembic version of the %{cyan!}{}%{reset}%{cyan} " "plugin to HEAD%{reset}") for plugin in plugin_engine.get_active_plugins().itervalues(): if not os.path.exists(plugin.alembic_versions_path): continue if verbose: print(plugin_msg.format(plugin.name)) with plugin.plugin_context(): stamp(revision='heads') # Retrieve the table list again, just in case we created unexpected tables tables = get_all_tables(db) tables['public'] = [ t for t in tables['public'] if not t.startswith('alembic_version') ] if any(tables.viewvalues()): if verbose: print(cformat('%{red}Your database is not empty!')) print( cformat( '%{yellow}If you just added a new table/model, create an alembic revision instead!' )) print() print('Tables in your database:') for schema, schema_tables in sorted(tables.items()): for t in schema_tables: print( cformat( ' * %{cyan}{}%{reset}.%{cyan!}{}%{reset}').format( schema, t)) return create_all_tables(db, verbose=verbose, add_initial_data=(not empty))
def get_context(self): if self._context is None: self._context = context = {} self._info = [] add_to_context = partial(_add_to_context, context, self._info) add_to_context_multi = partial(_add_to_context_multi, context, self._info) add_to_context_smart = partial(_add_to_context_smart, context, self._info) # Common stdlib modules self._info.append(cformat('*** %{magenta!}stdlib%{reset} ***')) DATETIME_ATTRS = ('date', 'time', 'datetime', 'timedelta') ORM_ATTRS = ('joinedload', 'defaultload', 'contains_eager', 'lazyload', 'noload', 'subqueryload', 'undefer') add_to_context_multi([getattr(datetime, attr) for attr in DATETIME_ATTRS] + [getattr(sqlalchemy.orm, attr) for attr in ORM_ATTRS] + [itertools, re, sys, os], color='yellow') # Legacy Indico self._info.append(cformat('*** %{magenta!}Legacy%{reset} ***')) add_to_context_multi([Conference, ConferenceHolder, CategoryManager, Catalog, IndexesHolder], color='green') add_to_context(LocalProxy(HelperMaKaCInfo.getMaKaCInfoInstance), 'minfo', color='green') # Models self._info.append(cformat('*** %{magenta!}Models%{reset} ***')) models = [cls for name, cls in sorted(db.Model._decl_class_registry.items(), key=itemgetter(0)) if hasattr(cls, '__table__')] add_to_context_smart(models) # Tasks self._info.append(cformat('*** %{magenta!}Tasks%{reset} ***')) tasks = [task for task in sorted(celery.tasks.values()) if not task.name.startswith('celery.')] add_to_context_smart(tasks, get_name=lambda x: x.name.replace('.', '_'), color='blue!') # Plugins self._info.append(cformat('*** %{magenta!}Plugins%{reset} ***')) plugins = [type(plugin) for plugin in sorted(plugin_engine.get_active_plugins().values(), key=attrgetter('name'))] add_to_context_multi(plugins, color='yellow!') # Utils self._info.append(cformat('*** %{magenta!}Misc%{reset} ***')) add_to_context(celery, 'celery', doc='celery app', color='blue!') add_to_context(DBMgr.getInstance(), 'dbi', doc='zodb db interface', color='cyan!') add_to_context(db, 'db', doc='sqlalchemy db interface', color='cyan!') add_to_context(transaction, doc='transaction module', color='cyan!') add_to_context(now_utc, 'now_utc', doc='get current utc time', color='cyan!') add_to_context(IndicoConfigWrapper(Config.getInstance()), 'config', doc='indico config') add_to_context(current_app, 'app', doc='flask app') add_to_context(lambda *a, **kw: server_to_utc(datetime.datetime(*a, **kw)), 'dt', doc='like datetime() but converted from localtime to utc') add_to_context(lambda x: ConferenceHolder().getById(x, True), 'E', doc='get event by id (Conference)') add_to_context(Event.get, 'EE', doc='get event by id (Event)') # Stuff from plugins signals.plugin.shell_context.send(add_to_context=add_to_context, add_to_context_multi=add_to_context_multi) return self._context
def generate_i18n_file(locale_name, react=False): root_path = os.path.join(current_app.root_path, 'translations') i18n_data = get_locale_data(root_path, locale_name, 'indico', react=react) if not i18n_data: # Dummy data, not having the indico domain would cause lots of failures i18n_data = {'indico': {'': {'domain': 'indico', 'lang': locale_name}}} for pid, plugin in plugin_engine.get_active_plugins().iteritems(): data = {} if plugin.translation_path: data = get_locale_data(plugin.translation_path, locale_name, pid, react=react) if not data: # Dummy entry so we can still load the domain data = {pid: {'': {'domain': pid, 'lang': locale_name}}} i18n_data.update(data) return json.dumps(i18n_data)
def _process(self): plugins = [p for p in plugin_engine.get_active_plugins().viewvalues()] categories = defaultdict(list) other = [] for plugin in plugins: if plugin.category: categories[plugin.category].append(plugin) else: other.append(plugin) # Sort the plugins of each category in alphabetic order and in a way that the internal plugins are always # listed in the front for category in categories: categories[category].sort(key=attrgetter("configurable", "title")) ordered_categories = OrderedDict(sorted(categories.items())) if other: ordered_categories[PluginCategory.other] = other return WPPlugins.render_template("index.html", categorized_plugins=ordered_categories)
def _process(self): plugins = [p for p in plugin_engine.get_active_plugins().values()] categories = defaultdict(list) other = [] for plugin in plugins: if plugin.category: categories[plugin.category].append(plugin) else: other.append(plugin) # Sort the plugins of each category in alphabetic order and in a way that the internal plugins are always # listed in the front for category in categories: categories[category].sort(key=attrgetter('configurable', 'title')) ordered_categories = dict(sorted(categories.items())) if other: ordered_categories[PluginCategory.other] = sorted(other, key=attrgetter('configurable', 'title')) return WPPlugins.render_template('index.html', categorized_plugins=ordered_categories)
def get_context(self): if self._context is None: self._context = context = {} self._info = [] add_to_context = partial(_add_to_context, context, self._info) add_to_context_multi = partial(_add_to_context_multi, context, self._info) add_to_context_smart = partial(_add_to_context_smart, context, self._info) # Common stdlib modules self._info.append(cformat('*** %{magenta!}stdlib%{reset} ***')) add_to_context_multi([getattr(datetime, attr) for attr in ('date', 'time', 'datetime', 'timedelta')] + [itertools], color='yellow') # Legacy Indico self._info.append(cformat('*** %{magenta!}Legacy%{reset} ***')) add_to_context_multi([Conference, ConferenceHolder, CategoryManager, Catalog, IndexesHolder], color='green') add_to_context(LocalProxy(HelperMaKaCInfo.getMaKaCInfoInstance), 'minfo', color='green') # Models self._info.append(cformat('*** %{magenta!}Models%{reset} ***')) models = [cls for name, cls in sorted(db.Model._decl_class_registry.items(), key=itemgetter(0)) if hasattr(cls, '__table__')] add_to_context_smart(models) # Tasks self._info.append(cformat('*** %{magenta!}Tasks%{reset} ***')) celery.loader.import_default_modules() # load all tasks tasks = [task for task in sorted(celery.tasks.values()) if not task.name.startswith('celery.')] add_to_context_smart(tasks, get_name=lambda x: x.name.replace('.', '_'), color='blue!') # Plugins self._info.append(cformat('*** %{magenta!}Plugins%{reset} ***')) plugins = [type(plugin) for plugin in sorted(plugin_engine.get_active_plugins().values(), key=attrgetter('name'))] add_to_context_multi(plugins, color='yellow!') # Utils self._info.append(cformat('*** %{magenta!}Misc%{reset} ***')) add_to_context(celery, 'celery', doc='celery app', color='blue!') add_to_context(DBMgr.getInstance(), 'dbi', doc='zodb db interface', color='cyan!') add_to_context(db, 'db', doc='sqlalchemy db interface', color='cyan!') add_to_context(transaction, doc='transaction module', color='cyan!') add_to_context(IndicoConfigWrapper(Config.getInstance()), 'config', doc='indico config') add_to_context(current_app, 'app', doc='flask app') # Stuff from plugins signals.plugin.shell_context.send(add_to_context=add_to_context, add_to_context_multi=add_to_context_multi) return self._context
def _make_shell_context(): context = {} info = [cformat('%{white!}Available objects')] add_to_context = partial(_add_to_context, context, info) add_to_context_multi = partial(_add_to_context_multi, context, info) add_to_context_smart = partial(_add_to_context_smart, context, info) # Common stdlib modules info.append(cformat('*** %{magenta!}stdlib%{reset} ***')) DATETIME_ATTRS = ('date', 'time', 'datetime', 'timedelta') ORM_ATTRS = ('joinedload', 'defaultload', 'contains_eager', 'lazyload', 'noload', 'subqueryload', 'undefer', 'undefer_group', 'load_only') add_to_context_multi([getattr(datetime, attr) for attr in DATETIME_ATTRS] + [getattr(sqlalchemy.orm, attr) for attr in ORM_ATTRS] + [itertools, re, sys, os], color='yellow') # Models info.append(cformat('*** %{magenta!}Models%{reset} ***')) models = [cls for name, cls in sorted(db.Model._decl_class_registry.items(), key=itemgetter(0)) if hasattr(cls, '__table__')] add_to_context_smart(models) # Tasks info.append(cformat('*** %{magenta!}Tasks%{reset} ***')) tasks = [task for task in sorted(celery.tasks.values()) if not task.name.startswith('celery.')] add_to_context_smart(tasks, get_name=lambda x: x.name.replace('.', '_'), color='blue!') # Plugins info.append(cformat('*** %{magenta!}Plugins%{reset} ***')) plugins = [type(plugin) for plugin in sorted(plugin_engine.get_active_plugins().values(), key=attrgetter('name'))] add_to_context_multi(plugins, color='yellow!') # Utils info.append(cformat('*** %{magenta!}Misc%{reset} ***')) add_to_context(celery, 'celery', doc='celery app', color='blue!') add_to_context(db, 'db', doc='sqlalchemy db interface', color='cyan!') add_to_context(now_utc, 'now_utc', doc='get current utc time', color='cyan!') add_to_context(config, 'config', doc='indico config') add_to_context(current_app, 'app', doc='flask app') add_to_context(lambda *a, **kw: server_to_utc(datetime.datetime(*a, **kw)), 'dt', doc='like datetime() but converted from localtime to utc') add_to_context(Event.get, 'EE', doc='get event by id') # Stuff from plugins signals.plugin.shell_context.send(add_to_context=add_to_context, add_to_context_multi=add_to_context_multi) return context, info
def __call__(self, app=None, *args, **kwargs): PluginScriptDirectory.dir = os.path.join(app.root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory with app.app_context(): active_plugins = plugin_engine.get_active_plugins() plugins = set(kwargs.pop('plugins')) if plugins: invalid_plugins = plugins - active_plugins.viewkeys() if invalid_plugins: print cformat('%{red!}Invalid plugin(s) specified: {}').format(', '.join(invalid_plugins)) sys.exit(1) for plugin in active_plugins.itervalues(): if plugins and plugin.name not in plugins: continue if not os.path.exists(plugin.alembic_versions_path): print cformat("%{cyan}skipping plugin '{}' (no migrations folder)").format(plugin.name) continue print cformat("%{cyan!}executing command for plugin '{}'").format(plugin.name) with plugin.plugin_context(): super(PluginDBCommand, self).__call__(app, *args, **kwargs)
def prepare_db(empty=False, root_path=None, verbose=True): """Initialize an empty database (create tables, set alembic rev to HEAD).""" if not _require_pg_version('9.6'): return if not _require_encoding('UTF8'): return if not _require_extensions('unaccent', 'pg_trgm'): return root_path = root_path or current_app.root_path tables = get_all_tables(db) if 'alembic_version' not in tables['public']: if verbose: print(cformat('%{green}Setting the alembic version to HEAD')) stamp(directory=os.path.join(root_path, 'migrations'), revision='heads') PluginScriptDirectory.dir = os.path.join(root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory plugin_msg = cformat("%{cyan}Setting the alembic version of the %{cyan!}{}%{reset}%{cyan} " "plugin to HEAD%{reset}") for plugin in plugin_engine.get_active_plugins().itervalues(): if not os.path.exists(plugin.alembic_versions_path): continue if verbose: print(plugin_msg.format(plugin.name)) with plugin.plugin_context(): stamp(revision='heads') # Retrieve the table list again, just in case we created unexpected tables tables = get_all_tables(db) tables['public'] = [t for t in tables['public'] if not t.startswith('alembic_version')] if any(tables.viewvalues()): if verbose: print(cformat('%{red}Your database is not empty!')) print(cformat('%{yellow}If you just added a new table/model, create an alembic revision instead!')) print() print('Tables in your database:') for schema, schema_tables in sorted(tables.items()): for t in schema_tables: print(cformat(' * %{cyan}{}%{reset}.%{cyan!}{}%{reset}').format(schema, t)) return create_all_tables(db, verbose=verbose, add_initial_data=(not empty))
def _call_with_plugins(*args, **kwargs): func = kwargs.pop('_func') ctx = click.get_current_context() all_plugins = ctx.parent.params['all_plugins'] plugin = ctx.parent.params['plugin'] if plugin: plugins = {plugin_engine.get_plugin(plugin)} elif all_plugins: plugins = set(plugin_engine.get_active_plugins().viewvalues()) else: plugins = None if plugins is None: func(*args, **kwargs) else: PluginScriptDirectory.dir = os.path.join(current_app.root_path, 'core', 'plugins', 'alembic') alembic.command.ScriptDirectory = PluginScriptDirectory for plugin in plugins: if not os.path.exists(plugin.alembic_versions_path): print cformat("%{cyan}skipping plugin '{}' (no migrations folder)").format(plugin.name) continue print cformat("%{cyan!}executing command for plugin '{}'").format(plugin.name) with plugin.plugin_context(): func(*args, **kwargs)
def _get_menu_cache_data(event): from indico.core.plugins import plugin_engine cache_key = unicode(event.id) plugin_hash = crc32(','.join(sorted(plugin_engine.get_active_plugins()))) cache_version = '{}:{}'.format(indico.__version__, plugin_hash) return cache_key, cache_version
def _get_menu_cache_data(event): from indico.core.plugins import plugin_engine cache_key = unicode(event.id) plugin_hash = crc32(','.join(sorted(plugin_engine.get_active_plugins()))) cache_version = '{}:{}'.format(MaKaC.__version__, plugin_hash) return cache_key, cache_version
def get_vc_plugins(): """Returns a dict containing the available videoconference plugins.""" from indico.modules.vc import VCPluginMixin return {p.service_name: p for p in plugin_engine.get_active_plugins().itervalues() if isinstance(p, VCPluginMixin)}
def menu_entries_for_event(event): from indico.core.plugins import plugin_engine custom_menu_enabled = layout_settings.get(event, 'use_custom_menu') entries = MenuEntry.get_for_event(event) if custom_menu_enabled else [] signal_entries = get_menu_entries_from_signal() cache_key = unicode(event.id) plugin_hash = crc32(','.join(sorted(plugin_engine.get_active_plugins()))) cache_version = '{}:{}'.format(MaKaC.__version__, plugin_hash) processed = entries and _cache.get(cache_key) == cache_version if not processed: # menu entries from signal pos_gen = count(start=(entries[-1].position + 1) if entries else 0) entry_names = {entry.name for entry in entries} # Keeping only new entries from the signal new_entry_names = signal_entries.viewkeys() - entry_names # Mapping children data to their parent children = defaultdict(list) for name, data in signal_entries.iteritems(): if name in new_entry_names and data.parent is not None: children[data.parent].append(data) # Building the entries new_entries = [ _build_menu_entry(event, custom_menu_enabled, data, next(pos_gen), children=children.get(data.name)) for ( name, data) in sorted(signal_entries.iteritems(), key=lambda (name, data): _menu_entry_key(data)) if name in new_entry_names and data.parent is None ] if custom_menu_enabled: with db.tmp_session() as sess: sess.add_all(new_entries) try: sess.commit() except IntegrityError as e: # If there are two parallel requests trying to insert a new menu # item one of them will fail with an error due to the unique index. # If the IntegrityError involves that index, we assume it's just the # race condition and ignore it. sess.rollback() if 'ix_uq_menu_entries_event_id_name' not in unicode( e.message): raise else: _cache.set(cache_key, cache_version) entries = MenuEntry.get_for_event(event) else: entries = new_entries return entries
def _get_menu_cache_data(event): from indico.core.plugins import plugin_engine cache_key = str(event.id) plugin_hash = crc32(','.join(sorted(plugin_engine.get_active_plugins()))) cache_version = f'{indico.__version__}:{plugin_hash}' return cache_key, cache_version