File: help.py

package info (click to toggle)
python-stem 1.2.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 4,568 kB
  • ctags: 2,036
  • sloc: python: 20,108; makefile: 127; sh: 3
file content (142 lines) | stat: -rw-r--r-- 3,661 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
"""
Provides our /help responses.
"""

from stem.interpreter import (
  STANDARD_OUTPUT,
  BOLD_OUTPUT,
  ERROR_OUTPUT,
  msg,
  uses_settings,
)

from stem.util.term import format

try:
  # added in python 3.2
  from functools import lru_cache
except ImportError:
  from stem.util.lru_cache import lru_cache


def response(controller, arg):
  """
  Provides our /help response.

  :param stem.control.Controller controller: tor control connection
  :param str arg: controller or interpreter command to provide help output for

  :returns: **str** with our help response
  """

  # Normalizing inputs first so we can better cache responses.

  return _response(controller, _normalize(arg))


def _normalize(arg):
  arg = arg.upper()

  # If there's multiple arguments then just take the first. This is
  # particularly likely if they're trying to query a full command (for
  # instance "/help GETINFO version")

  arg = arg.split(' ')[0]

  # strip slash if someone enters an interpreter command (ex. "/help /help")

  if arg.startswith('/'):
    arg = arg[1:]

  return arg


@lru_cache()
@uses_settings
def _response(controller, arg, config):
  if not arg:
    return _general_help()

  usage_info = config.get('help.usage', {})

  if not arg in usage_info:
    return format("No help information available for '%s'..." % arg, *ERROR_OUTPUT)

  output = format(usage_info[arg] + '\n', *BOLD_OUTPUT)

  description = config.get('help.description.%s' % arg.lower(), '')

  for line in description.splitlines():
    output += format('  ' + line, *STANDARD_OUTPUT) + '\n'

  output += '\n'

  if arg == 'GETINFO':
    results = controller.get_info('info/names', None)

    if results:
      for line in results.splitlines():
        if ' -- ' in line:
          opt, summary = line.split(' -- ', 1)

          output += format('%-33s' % opt, *BOLD_OUTPUT)
          output += format(' - %s' % summary, *STANDARD_OUTPUT) + '\n'
  elif arg == 'GETCONF':
    results = controller.get_info('config/names', None)

    if results:
      options = [opt.split(' ', 1)[0] for opt in results.splitlines()]

      for i in range(0, len(options), 2):
        line = ''

        for entry in options[i:i + 2]:
          line += '%-42s' % entry

        output += format(line.rstrip(), *STANDARD_OUTPUT) + '\n'
  elif arg == 'SIGNAL':
    signal_options = config.get('help.signal.options', {})

    for signal, summary in signal_options.items():
      output += format('%-15s' % signal, *BOLD_OUTPUT)
      output += format(' - %s' % summary, *STANDARD_OUTPUT) + '\n'
  elif arg == 'SETEVENTS':
    results = controller.get_info('events/names', None)

    if results:
      entries = results.split()

      # displays four columns of 20 characters

      for i in range(0, len(entries), 4):
        line = ''

        for entry in entries[i:i + 4]:
          line += '%-20s' % entry

        output += format(line.rstrip(), *STANDARD_OUTPUT) + '\n'
  elif arg == 'USEFEATURE':
    results = controller.get_info('features/names', None)

    if results:
      output += format(results, *STANDARD_OUTPUT) + '\n'
  elif arg in ('LOADCONF', 'POSTDESCRIPTOR'):
    # gives a warning that this option isn't yet implemented
    output += format(msg('msg.multiline_unimplemented_notice'), *ERROR_OUTPUT) + '\n'

  return output.rstrip()


def _general_help():
  lines = []

  for line in msg('help.general').splitlines():
    div = line.find(' - ')

    if div != -1:
      cmd, description = line[:div], line[div:]
      lines.append(format(cmd, *BOLD_OUTPUT) + format(description, *STANDARD_OUTPUT))
    else:
      lines.append(format(line, *BOLD_OUTPUT))

  return '\n'.join(lines)