def render_admin_panel(self, req, category, page, path_info): """Process a request for an admin panel.""" db = self.env.get_db_cnx() cursor = db.cursor() if req.method == 'POST': if req.args.get('add'): f = req.args.get('from').strip() t = req.args.get('to').strip() enabled = req.args.get('enabled', "").strip() enabled = enabled and (enabled != "0") self._add_redirect(cursor, f, t, enabled) db.commit() add_notice(req, _('Redirect from "%(frompath)s" to "%(topath)s" has been added.', frompath=f, topath=t)) elif req.args.get('remove'): selected = req.args.get('selected') if selected: if not isinstance(selected, list): selected = [selected] for redirect in selected: self._remove_redirect(cursor, redirect) db.commit() msg = ngettext('Selected redirect has been removed.', 'Selected redirects have been removed.', len(selected)) add_notice(req, msg) elif req.args.get('enable'): selected = req.args.get('selected') if selected: if not isinstance(selected, list): selected = [selected] for redirect in selected: self._enable_redirect(cursor, redirect) db.commit() msg = ngettext('Selected redirect has been enabled.', 'Selected redirects have been enabled.', len(selected)) add_notice(req, msg) elif req.args.get('disable'): selected = req.args.get('selected') if selected: if not isinstance(selected, list): selected = [selected] for redirect in selected: self._disable_redirect(cursor, redirect) db.commit() msg = ngettext('Selected redirect has been disabled.', 'Selected redirects have been disabled.', len(selected)) add_notice(req, msg) req.redirect(req.href.admin(category, page)) cursor.execute("SELECT frompath, topath, enabled FROM redirects ORDER BY frompath, topath") redirects = cursor.fetchall() return ('admin_redirects.html', { 'redirects': redirects, })
def _do_update(self, req): """Update component enable state.""" components = req.args.getlist('component') enabled = req.args.getlist('enable') added, removed = [], [] # FIXME: this needs to be more intelligent and minimize multiple # component names to prefix rules for component in components: is_enabled = bool(self.env.is_component_enabled(component)) must_enable = component in enabled if is_enabled != must_enable: self.config.set('components', component, 'disabled' if is_enabled else 'enabled') self.log.info("%sabling component %s", "Dis" if is_enabled else "En", component) if must_enable: added.append(component) else: removed.append(component) if added or removed: def make_list(items): parts = [item.rsplit('.', 1) for item in items] return tag.table(tag.tbody( tag.tr(tag.td(c, class_='trac-name'), tag.td('(%s.*)' % m, class_='trac-name')) for m, c in parts), class_='trac-pluglist') added.sort() removed.sort() notices = [] if removed: msg = ngettext("The following component has been disabled:", "The following components have been disabled:", len(removed)) notices.append(tag(msg, make_list(removed))) if added: msg = ngettext("The following component has been enabled:", "The following components have been enabled:", len(added)) notices.append(tag(msg, make_list(added))) # set the default value of options for only the enabled components for component in added: self.config.set_defaults(component=component) _save_config(self.config, req, self.log, notices)
def _do_update(self, req): """Update component enablement.""" components = req.args.getlist('component') enabled = req.args.getlist('enable') added, removed = [], [] # FIXME: this needs to be more intelligent and minimize multiple # component names to prefix rules for component in components: is_enabled = bool(self.env.is_component_enabled(component)) must_enable = component in enabled if is_enabled != must_enable: self.config.set('components', component, 'disabled' if is_enabled else 'enabled') self.log.info("%sabling component %s", "Dis" if is_enabled else "En", component) if must_enable: added.append(component) else: removed.append(component) if added or removed: def make_list(items): parts = [item.rsplit('.', 1) for item in items] return tag.table(tag.tbody( tag.tr(tag.td(c, class_='trac-name'), tag.td('(%s.*)' % m, class_='trac-name')) for m, c in parts), class_='trac-pluglist') added.sort() removed.sort() notices = [] if removed: msg = ngettext("The following component has been disabled:", "The following components have been disabled:", len(removed)) notices.append(tag(msg, make_list(removed))) if added: msg = ngettext("The following component has been enabled:", "The following components have been enabled:", len(added)) notices.append(tag(msg, make_list(added))) # set the default value of options for only the enabled components for component in added: self.config.set_defaults(component=component) _save_config(self.config, req, self.log, notices)
def _sync(self, reponame, rev, clean): rm = RepositoryManager(self.env) if reponame == '*': if rev is not None: raise TracError(_('Cannot synchronize a single revision ' 'on multiple repositories')) repositories = rm.get_real_repositories() else: if is_default(reponame): reponame = '' repos = rm.get_repository(reponame) if repos is None: raise TracError(_("Repository '%(repo)s' not found", repo=reponame or '(default)')) if rev is not None: repos.sync_changeset(rev) printout(_('%(rev)s resynced on %(reponame)s.', rev=rev, reponame=repos.reponame or '(default)')) return repositories = [repos] for repos in sorted(repositories, key=lambda r: r.reponame): printout(_('Resyncing repository history for %(reponame)s... ', reponame=repos.reponame or '(default)')) repos.sync(self._sync_feedback, clean=clean) for cnt, in self.env.db_query( "SELECT count(rev) FROM revision WHERE repos=%s", (repos.id,)): printout(ngettext('%(num)s revision cached.', '%(num)s revisions cached.', num=cnt)) printout(_('Done.'))
def do_help(self, line=None): arg = self.arg_tokenize(line) if arg[0]: cmd_mgr = None doc = getattr(self, "_help_" + arg[0], None) if doc is None and self.env_check(): cmd_mgr = self.cmd_mgr doc = cmd_mgr.get_command_help(arg) if doc: self.print_doc(doc) else: printerr(_("No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(arg))) cmds = None if cmd_mgr: cmds = cmd_mgr.get_similar_commands(arg[0]) if cmds: printout('') printout(ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout(_("trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) if not self.interactive: print() printout(_("Usage: trac-admin </path/to/projenv> " "[command [subcommand] [option ...]]\n")) printout(_("Invoking trac-admin without command starts " "interactive mode.\n")) env = self.env if self.env_check() else None self.print_doc(self.all_docs(env), short=True)
def _do_product_admin(self, prefix, *args): mgr = self.product_admincmd_mgr(prefix) if args and args[0] in self.GLOBAL_COMMANDS: raise AdminCommandError('%s command not supported for products' % (args[0],)) if args and args[0] == 'help': help_args = args[1:] if help_args: doc = mgr.get_command_help(list(help_args)) if doc: TracAdmin.print_doc(doc) else: printerr(_("No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(help_args))) cmds = mgr.get_similar_commands(help_args[0]) if cmds: printout('') printout(ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout(_("trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) env = mgr.env TracAdmin.print_doc(TracAdmin.all_docs(env), short=True) else: mgr.execute_command(*args)
def _sync(self, reponame, rev, clean): rm = RepositoryManager(self.env) if reponame == '*': if rev is not None: raise TracError(_('Cannot synchronize a single revision ' 'on multiple repositories')) repositories = rm.get_real_repositories() else: if is_default(reponame): reponame = '' repos = rm.get_repository(reponame) if repos is None: raise TracError(_("Repository '%(repo)s' not found", repo=reponame or '(default)')) if rev is not None: repos.sync_changeset(rev) printout(_('%(rev)s resynced on %(reponame)s.', rev=rev, reponame=repos.reponame or '(default)')) return repositories = [repos] db = self.env.get_db_cnx() for repos in sorted(repositories, key=lambda r: r.reponame): printout(_('Resyncing repository history for %(reponame)s... ', reponame=repos.reponame or '(default)')) repos.sync(self._sync_feedback, clean=clean) cursor = db.cursor() cursor.execute("SELECT count(rev) FROM revision WHERE repos=%s", (repos.id,)) for cnt, in cursor: printout(ngettext('%(num)s revision cached.', '%(num)s revisions cached.', num=cnt)) printout(_('Done.'))
def _do_product_admin(self, prefix, *args): mgr = self.product_admincmd_mgr(prefix) if args and args[0] in self.GLOBAL_COMMANDS: raise AdminCommandError('%s command not supported for products' % (args[0], )) if args and args[0] == 'help': help_args = args[1:] if help_args: doc = mgr.get_command_help(list(help_args)) if doc: TracAdmin.print_doc(doc) else: printerr( _( "No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(help_args))) cmds = mgr.get_similar_commands(help_args[0]) if cmds: printout('') printout( ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout( _( "trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) env = mgr.env TracAdmin.print_doc(TracAdmin.all_docs(env), short=True) else: mgr.execute_command(*args)
def handle_edit_locale_admins(self, req, locale_id): if not locale_id: req.redirect(req.href.admin('translations', 'locales')) Session = session(self.env) locale = Session.query(Locale).get(int(locale_id)) known_users = self.env.get_known_users() errors = [] perm = PermissionSystem(self.env) sids_without_necessary_perms = [] for admin in locale.admins: if not 'L10N_MODERATE' in perm.get_user_permissions(admin.sid): sids_without_necessary_perms.append(admin.sid) if sids_without_necessary_perms: msg = ngettext( "%s does not have the required permissions to administrate." % \ ', '.join(["'%s'" % s for s in sids_without_necessary_perms]), "%s don't have the required permissions to administrate." % \ ', '.join(["'%s'" % s for s in sids_without_necessary_perms]), len(sids_without_necessary_perms)) errors.append( tag(msg, _(" Don't forget to "), tag.a(_('update permissions'), href=req.href.admin('general', 'perm')), '.')) if req.method == 'POST' and len(req.args.getlist('admins')) >= 1: current_admins = req.args.getlist('current_admins') selected = req.args.getlist('admins') self.log.debug('Current Admins: %s', current_admins) self.log.debug('Selected Admins: %s', selected) allow_delete_admins = len(selected) >= 1 if not allow_delete_admins: errors.append( tag(_("There must be at least on admin for each locale."))) for admin in current_admins: if not allow_delete_admins: break if admin not in selected: locale_admin = Session.query(LocaleAdmin). \ filter(locale_admin_table.c.sid==admin).first() Session.delete(locale_admin) for admin in selected: if admin not in locale.admins: locale.admins.append(LocaleAdmin(locale, admin)) Session.commit() req.redirect(req.href.admin('translations', 'locales')) elif req.method == 'POST' and len(req.args.getlist('admins')) < 1: errors.append( tag(_("There must be at least on admin for each locale."))) data = {'locale': locale, 'known_users': known_users} if errors: data['error'] = tag.ul(*[tag.li(e) for e in errors if e]) return 'l10n_admin_locale_admins.html', data
def delete_locale(self, req): selected = req.args.getlist('sel') Session = session(self.env) for id in selected: Session.delete(Session.query(Locale).get(int(id))) Session.commit() add_notice(req, ngettext("Locale deleted.", "Locales deleted.", len(selected))) return {}
def delete_catalogs(self, req): selected = req.args.getlist('sel') Session = session(self.env) for catalog in selected: Session.delete(Session.query(Catalog).get(int(catalog))) add_notice(req, ngettext("Catalog deleted.", "Catalogs deleted.", len(selected))) Session.commit() return {}
def _do_resync(self, reponame): rm = RepositoryManager(self.env) if reponame == '*': repositories = rm.get_real_repositories() else: if is_default(reponame): reponame = '' repos = rm.get_repository(reponame) if repos is None: raise TracError( _("Repository '%(repo)s' not found", repo=reponame or '(default)')) repositories = [repos] Changeset = namedtuple('changeset', 'repos rev message author date') for repos in sorted(repositories, key=lambda r: r.reponame): printout( _('Resyncing repository history for %(reponame)s... ', reponame=repos.reponame or '(default)')) with self.env.db_transaction as db: db( """ DELETE FROM codereviewer_map WHERE repo=%s """, (repos.reponame, )) for time, author, message, rev in db( """ SELECT time, author, message, rev FROM revision WHERE repos=%s ORDER BY time """, (repos.id, )): cset = Changeset(repos, rev, message, author, from_utimestamp(time)) self._map(repos.reponame, cset) self._sync_feedback(rev) for cnt, in self.env.db_query( "SELECT count(rev) FROM revision WHERE repos=%s", (repos.id, )): printout( ngettext('%(num)s revision cached.', '%(num)s revisions cached.', num=cnt)) printout(_("Done."))
def pretty_size(size, format='%.1f'): """Pretty print content size information with appropriate unit. :param size: number of bytes :param format: can be used to adjust the precision shown """ if size is None: return '' jump = 1024 if size < jump: from trac.util.translation import ngettext return ngettext("%(num)d byte", "%(num)d bytes", num=size) units = ['KB', 'MB', 'GB', 'TB'] i = 0 while size >= jump and i < len(units): i += 1 size /= 1024. return (format + ' %s') % (size, units[i - 1])
def filter_stream(self, req, method, filename, stream, data): """ Adds project follower information in project summary block:: Followers: You and 1 other Followers: You and 10 others Followers: 10 """ # Filter only the summary table wiki macro if filename != 'multiproject_summary.html': return stream # Load project and followers info project = Project.get(self.env) watchers, is_watching = self._get_status(req, project.id) # By default show only the number status = tag.span(watchers) # Show link to user preferences if is_watching: status = tag.a('You', href=req.href('../home/prefs/following')) # And others? watchers -= 1 if watchers: status += ngettext(" and %(count)s other", " and %(count)s others", watchers, count=watchers) # Add following information into project summary block trans = Transformer('//div[@class="summary"]/table').append( tag.tr( tag.th('Followers:'), tag.td(status) ) ) return stream | trans
def pretty_timedelta(time1, time2=None, resolution=None): """Calculate time delta between two `datetime` objects. (the result is somewhat imprecise, only use for prettyprinting). If either `time1` or `time2` is None, the current time will be used instead. """ time1 = to_datetime(time1) time2 = to_datetime(time2) if time1 > time2: time2, time1 = time1, time2 diff = time2 - time1 age_s = int(diff.days * 86400 + diff.seconds) if resolution and age_s < resolution: return '' if age_s <= 60 * 1.9: return ngettext('%(num)i second', '%(num)i seconds', age_s) for u, format_units in _units: r = float(age_s) / float(u) if r >= 1.9: r = int(round(r)) return format_units(r) return ''
def do_help(self, line=None): arg = self.arg_tokenize(line) if arg[0]: cmd_mgr = None doc = getattr(self, "_help_" + arg[0], None) if doc is None and self.env_check(): cmd_mgr = self.cmd_mgr doc = cmd_mgr.get_command_help(arg) if doc: self.print_doc(doc) else: printerr(_("No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(arg))) cmds = None if cmd_mgr: cmds = cmd_mgr.get_similar_commands(arg[0]) if cmds: printout('') printout(ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout(_("trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) if not self.interactive: print() printout(_("Usage: trac-admin </path/to/projenv> " "[command [subcommand] [option ...]]\n") ) printout(_("Invoking trac-admin without command starts " "interactive mode.\n")) env = self.env if self.env_check() else None self.print_doc(self.all_docs(env), short=True)
def _sync(self, reponame, rev, clean): rm = RepositoryManager(self.env) if reponame == "*": if rev is not None: raise TracError(_("Cannot synchronize a single revision " "on multiple repositories")) repositories = rm.get_real_repositories() else: if is_default(reponame): reponame = "" repos = rm.get_repository(reponame) if repos is None: raise TracError(_("Repository '%(repo)s' not found", repo=reponame or "(default)")) if rev is not None: repos.sync_changeset(rev) printout(_("%(rev)s resynced on %(reponame)s.", rev=rev, reponame=repos.reponame or "(default)")) return repositories = [repos] for repos in sorted(repositories, key=lambda r: r.reponame): printout(_("Resyncing repository history for %(reponame)s... ", reponame=repos.reponame or "(default)")) repos.sync(self._sync_feedback, clean=clean) for (cnt,) in self.env.db_query("SELECT count(rev) FROM revision WHERE repos=%s", (repos.id,)): printout(ngettext("%(num)s revision cached.", "%(num)s revisions cached.", num=cnt)) printout(_("Done."))
def to_utimestamp(dt): """Return a microsecond POSIX timestamp for the given `datetime`.""" if not dt: return 0 diff = dt - _epoc return (diff.days * 86400000000L + diff.seconds * 1000000 + diff.microseconds) def from_utimestamp(ts): """Return the `datetime` for the given microsecond POSIX timestamp.""" return _epoc + timedelta(microseconds=ts or 0) # -- formatting _units = ( (3600*24*365, lambda r: ngettext('%(num)d year', '%(num)d years', r)), (3600*24*30, lambda r: ngettext('%(num)d month', '%(num)d months', r)), (3600*24*7, lambda r: ngettext('%(num)d week', '%(num)d weeks', r)), (3600*24, lambda r: ngettext('%(num)d day', '%(num)d days', r)), (3600, lambda r: ngettext('%(num)d hour', '%(num)d hours', r)), (60, lambda r: ngettext('%(num)d minute', '%(num)d minutes', r))) def pretty_timedelta(time1, time2=None, resolution=None): """Calculate time delta between two `datetime` objects. (the result is somewhat imprecise, only use for prettyprinting). If either `time1` or `time2` is None, the current time will be used instead. """ time1 = to_datetime(time1) time2 = to_datetime(time2)
def add_locale(self, req): data = {} errors = [] catalog_template_id = req.args.get('catalog_template', None) locale = req.args.get('locale') locale_admins = req.args.getlist('admins') def add_error(error): errors.append(error) data['error'] = tag.ul(*[tag.li(e) for e in errors if e]) data['locale'] = locale return data if not catalog_template_id: errors.append(_("You must first create a catalog template")) if not locale: return add_error(_("You must define the new catalog's locale")) if not locale_admins: return add_error(_("You must define at least one locale admin")) Session = session(self.env) catalog = Session.query(Catalog).get(catalog_template_id) num_plurals = get_plural(locale=locale).num_plurals _locale = Session.query(Locale).filter_by(locale=locale, catalog_id=catalog.id).first() if _locale: data['locale'] = _locale return add_error(_("Locale Exists Already")) locale = Locale(catalog, locale, num_plurals) for sid in locale_admins: locale.admins.append(LocaleAdmin(locale, sid)) catalog.locales.append(locale) Session.commit() perm = PermissionSystem(self.env) sids_without_necessary_perms = [] for admin in locale.admins: if not 'L10N_MODERATE' in perm.get_user_permissions(admin.sid): sids_without_necessary_perms.append(admin.sid) if sids_without_necessary_perms: msg = ngettext( "%s does not have the required permissions to administrate." % \ ', '.join(["'%s'" % s for s in sids_without_necessary_perms]), "%s don't have the required permissions to administrate." % \ ', '.join(["'%s'" % s for s in sids_without_necessary_perms]), len(sids_without_necessary_perms)) add_error(tag(msg, _(" Don't forget to "), tag.a(_('update permissions'), href=req.href.admin('general', 'perm')), '.')) add_notice(req, _("Locale added.")) # Are we importing existing data locale_catalog_path = req.args.get('catalog') include_fuzzy = req.args.get('include_fuzzy') == '1' if not locale_catalog_path or locale_catalog_path == '/': return data repos = self.env.get_repository(req.authname) revision = repos.youngest_rev try: node = get_existing_node(req, repos, locale_catalog_path, revision) except NoSuchChangeset, e: raise ResourceNotFound(e.message, _('Invalid Changeset Number'))
if not dt: return 0 diff = dt - _epoc return (diff.days * 86400000000 + diff.seconds * 1000000 + diff.microseconds) def from_utimestamp(ts): """Return the `datetime` for the given microsecond POSIX timestamp.""" return _epoc + timedelta(microseconds=ts or 0) # -- formatting _units = ((3600 * 24 * 365, lambda r: ngettext('%(num)d year', '%(num)d years', r)), (3600 * 24 * 30, lambda r: ngettext('%(num)d month', '%(num)d months', r)), (3600 * 24 * 7, lambda r: ngettext('%(num)d week', '%(num)d weeks', r)), (3600 * 24, lambda r: ngettext('%(num)d day', '%(num)d days', r)), (3600, lambda r: ngettext('%(num)d hour', '%(num)d hours', r)), (60, lambda r: ngettext('%(num)d minute', '%(num)d minutes', r))) def pretty_timedelta(time1, time2=None, resolution=None): """Calculate time delta between two `datetime` objects. (the result is somewhat imprecise, only use for prettyprinting). If either `time1` or `time2` is None, the current time will be used instead.