Server : Apache System : Linux iad1-shared-b8-43 6.6.49-grsec-jammy+ #10 SMP Thu Sep 12 23:23:08 UTC 2024 x86_64 User : dh_edsupp ( 6597262) PHP Version : 8.2.26 Disable Function : NONE Directory : /lib/python3/dist-packages/trac/admin/ |
Upload File : |
# -*- coding: utf-8 -*- # # Copyright (C) 2006-2021 Edgewall Software # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at https://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at https://trac.edgewall.org/log/. import os import os.path import sys import traceback from trac.core import * from trac.util.text import levenshtein_distance from trac.util.translation import _, get_negotiated_locale, has_babel LANG = os.environ.get('LANG') console_date_format = '%Y-%m-%d' console_datetime_format = '%Y-%m-%d %H:%M:%S' console_date_format_hint = 'YYYY-MM-DD' class IAdminPanelProvider(Interface): """Extension point interface for adding panels to the web-based administration interface. """ def get_admin_panels(req): """Return a list of available admin panels. The items returned by this function must be tuples of the form `(category, category_label, page, page_label)`. """ def render_admin_panel(req, category, page, path_info): """Process a request for an admin panel. This function should return a tuple of the form `(template, data)`, where `template` is the name of the template to use and `data` is the data to use when rendering the template. """ class AdminCommandError(TracError): """Exception raised when an admin command cannot be executed.""" def __init__(self, msg, show_usage=False, cmd=None): TracError.__init__(self, msg) self.show_usage = show_usage self.cmd = cmd class IAdminCommandProvider(Interface): """Extension point interface for adding commands to the console administration interface `trac-admin`. """ def get_admin_commands(): """Return a list of available admin commands. The items returned by this function must be tuples of the form `(command, args, help, complete, execute)`, where `command` contains the space-separated command and sub-command names, `args` is a string describing the command arguments and `help` is the help text. The first paragraph of the help text is taken as a short help, shown in the list of commands. `complete` is called to auto-complete the command arguments, with the current list of arguments as its only argument. It should return a list of relevant values for the last argument in the list. `execute` is called to execute the command, with the command arguments passed as positional arguments. """ class AdminCommandManager(Component): """trac-admin command manager.""" providers = ExtensionPoint(IAdminCommandProvider) def get_command_help(self, args=[]): """Return help information for a set of commands.""" commands = [] for provider in self.providers: for cmd in provider.get_admin_commands() or []: parts = cmd[0].split() if parts[:len(args)] == args: commands.append(cmd[:3]) commands.sort() return commands def complete_command(self, args, cmd_only=False): """Perform auto-completion on the given arguments.""" comp = [] for provider in self.providers: for cmd in provider.get_admin_commands() or []: parts = cmd[0].split() plen = min(len(parts), len(args) - 1) if args[:plen] != parts[:plen]: # Prefix doesn't match continue elif len(args) <= len(parts): # Command name comp.append(parts[len(args) - 1]) elif not cmd_only: # Arguments if cmd[3] is None: return [] return cmd[3](args[len(parts):]) or [] return comp def execute_command(self, *args): """Execute a command given by a list of arguments.""" args = list(args) for provider in self.providers: for cmd in provider.get_admin_commands() or []: parts = cmd[0].split() if args[:len(parts)] == parts: f = cmd[4] fargs = args[len(parts):] try: return f(*fargs) except AdminCommandError as e: e.cmd = ' '.join(parts) raise except TypeError: tb = traceback.extract_tb(sys.exc_info()[2]) if len(tb) == 1: raise AdminCommandError(_("Invalid arguments"), show_usage=True, cmd=' '.join(parts)) raise raise AdminCommandError(_("Command not found"), show_usage=True) def get_similar_commands(self, arg, n=5): if not arg: return [] cmds = set() for provider in self.providers: for cmd in provider.get_admin_commands() or []: cmds.add(cmd[0].split()[0]) # use only first token def score(cmd, arg): if cmd.startswith(arg): return 0 return levenshtein_distance(cmd, arg) / float(len(cmd) + len(arg)) similars = sorted((score(cmd, arg), cmd) for cmd in cmds) similars = [cmd for val, cmd in similars if val <= 0.5] return similars[:n] class PrefixList(list): """A list of prefixes for command argument auto-completion.""" def complete(self, text): return list({a for a in self if a.startswith(text)}) def path_startswith(path, prefix): return os.path.normcase(path).startswith(os.path.normcase(prefix)) class PathList(list): """A list of paths for command argument auto-completion.""" def complete(self, text): """Return the items in the list matching text.""" matches = list({a for a in self if path_startswith(a, text)}) if len(matches) == 1 and not os.path.isdir(matches[0]): matches[0] += ' ' return matches def get_dir_list(path, dirs_only=False): """Return a list of paths to filesystem entries in the same directory as the given path.""" dname = os.path.dirname(path) d = os.path.join(os.getcwd(), dname) result = PathList() try: dlist = os.listdir(d) except OSError: return result for entry in dlist: path = os.path.normpath(os.path.join(dname, entry)) try: if os.path.isdir(path): result.append(os.path.join(path, '')) elif not dirs_only: result.append(path) except OSError: pass return result def get_console_locale(env=None, lang=None, categories=('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG')): """Return negotiated locale for console by locale environments and [trac] default_language.""" if has_babel: from babel.core import UnknownLocaleError, parse_locale def normalize(value): if not value: return None try: return '_'.join(filter(None, parse_locale(value))) except: return None locales = [lang] for category in categories: value = os.environ.get(category) if not value: continue if category == 'LANGUAGE' and ':' in value: value = value.split(':')[0] locales.append(value) if env: locales.append(env.config.get('trac', 'default_language')) locales = list(filter(None, map(normalize, locales))) try: return get_negotiated_locale(locales) except UnknownLocaleError: pass return None