Package trac ::
Package admin ::
Module api
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C)2006-2009 Edgewall Software
4 # All rights reserved.
5 #
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://trac.edgewall.org/wiki/TracLicense.
9 #
10 # This software consists of voluntary contributions made by many
11 # individuals. For the exact contribution history, see the revision
12 # history and logs, available at http://trac.edgewall.org/log/.
13
14 import os.path
15 import sys
16 import traceback
17
18 from trac .core import *
19 from trac .util .text import levenshtein_distance
20 from trac .util .translation import _
21
22
23 console_date_format = '%Y-%m-%d'
24 console_datetime_format = '%Y-%m-%d %H:%M:%S'
25 console_date_format_hint = 'YYYY-MM-DD'
26
27
29 """Extension point interface for adding panels to the web-based
30 administration interface.
31 """
32
34 """Return a list of available admin panels.
35
36 The items returned by this function must be tuples of the form
37 `(category, category_label, page, page_label)`.
38 """
39
41 """Process a request for an admin panel.
42
43 This function should return a tuple of the form `(template, data)`,
44 where `template` is the name of the template to use and `data` is the
45 data to be passed to the template.
46 """
47
48
50 """Exception raised when an admin command cannot be executed."""
51 - def __init__ (self, msg, show_usage=False, cmd=None):
55
56
58 """Extension point interface for adding commands to the console
59 administration interface `trac-admin`.
60 """
61
63 """Return a list of available admin commands.
64
65 The items returned by this function must be tuples of the form
66 `(command, args, help, complete, execute)`, where `command` contains
67 the space-separated command and sub-command names, `args` is a string
68 describing the command arguments and `help` is the help text. The
69 first paragraph of the help text is taken as a short help, shown in the
70 list of commands.
71
72 `complete` is called to auto-complete the command arguments, with the
73 current list of arguments as its only argument. It should return a list
74 of relevant values for the last argument in the list.
75
76 `execute` is called to execute the command, with the command arguments
77 passed as positional arguments.
78 """
79
80
82 """trac-admin command manager."""
83
84 providers = ExtensionPoint (IAdminCommandProvider )
85
87 """Return help information for a set of commands."""
88 commands = []
89 for provider in self.providers :
90 for cmd in provider.get_admin_commands () or []:
91 parts = cmd[0].split()
92 if parts[:len(args )] == args :
93 commands.append(cmd[:3])
94 commands.sort()
95 return commands
96
98 """Perform auto-completion on the given arguments."""
99 comp = []
100 for provider in self.providers :
101 for cmd in provider.get_admin_commands () or []:
102 parts = cmd[0].split()
103 plen = min (len(parts), len(args ) - 1)
104 if args [:plen] != parts[:plen]: # Prefix doesn't match
105 continue
106 elif len(args ) <= len(parts): # Command name
107 comp.append(parts[len(args ) - 1])
108 elif not cmd_only: # Arguments
109 if cmd[3] is None:
110 return []
111 return cmd[3](args [len(parts):]) or []
112 return comp
113
115 """Execute a command given by a list of arguments."""
116 args = list(args )
117 for provider in self.providers :
118 for cmd in provider.get_admin_commands () or []:
119 parts = cmd[0].split()
120 if args [:len(parts)] == parts:
121 f = cmd[4]
122 fargs = args [len(parts):]
123 try:
124 return f(*fargs)
125 except AdminCommandError , e :
126 e .cmd = ' '.join (parts)
127 raise
128 except TypeError, e :
129 tb = traceback.extract_tb(sys.exc_info()[2])
130 if len(tb) == 1:
131 raise AdminCommandError (_ ("Invalid arguments"),
132 show_usage=True,
133 cmd=' '.join (parts))
134 raise
135 raise AdminCommandError (_ ("Command not found"), show_usage=True)
136
138 if not arg:
139 return []
140
141 cmds = set ()
142 for provider in self.providers :
143 for cmd in provider.get_admin_commands () or []:
144 cmds.add(cmd[0].split()[0]) # use only first token
145
146 def score(cmd, arg):
147 if cmd.startswith(arg):
148 return 0
149 return levenshtein_distance (cmd, arg) / float(len(cmd) + len(arg))
150 similars = sorted((score(cmd, arg), cmd) for cmd in cmds)
151 similars = [cmd for val, cmd in similars if val <= 0.5]
152 return similars[:n]