Completed
Push — master ( 5435dc...6f25c5 )
by
unknown
14s queued 12s
created

gvmtools.pyshell.main()   F

Complexity

Conditions 14

Size

Total Lines 102
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 69
dl 0
loc 102
rs 3.5345
c 0
b 0
f 0
cc 14
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like gvmtools.pyshell.main() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2018 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
import code
20
import logging
21
import os
22
import sys
23
24
from argparse import Namespace
25
26
from gvm import get_version as get_gvm_version
27
from gvm.protocols.gmp import Gmp
28
from gvm.protocols.latest import Osp
29
from gvm.transforms import EtreeCheckCommandTransform
30
31
from gvmtools import get_version
32
from gvmtools.helper import authenticate, run_script, do_not_run_as_root
33
from gvmtools.parser import (
34
    create_parser,
35
    create_connection,
36
    PROTOCOL_OSP,
37
    PROTOCOL_GMP,
38
)
39
40
__version__ = get_version()
41
__api_version__ = get_gvm_version()
42
43
logger = logging.getLogger(__name__)
44
45
HELP_TEXT = """
46
    Command line tool to access services via GMP (Greenbone Management
47
    Protocol) and OSP (Open Scanner Protocol)
48
49
    gvm-pyshell provides an interactive shell for GMP and OSP services.
50
51
    Example:
52
        >>> tasks = gmp.get_tasks()
53
        >>> task_names = tasks.xpath('task/name/text()')
54
        >>> print(task_names)
55
        ['Scan Task']
56
57
    The interactive shell can be exited with:
58
        Ctrl + D on Linux  or
59
        Ctrl + Z on Windows
60
61
    The protocol specifications for GMP and OSP are available at:
62
      https://docs.greenbone.net/index.html#api_documentation"""
63
64
65
class Help(object):
66
    """Help class to overwrite the help function from python itself.
67
    """
68
69
    def __call__(self):
70
        return print(HELP_TEXT)
71
72
    def __repr__(self):
73
        # do pwd command
74
        return HELP_TEXT
75
76
77
def main():
78
    do_not_run_as_root()
79
80
    parser = create_parser(description=HELP_TEXT, logfilename='gvm-pyshell.log')
81
82
    parser.add_protocol_argument()
83
84
    parser.add_argument(
85
        '-i',
86
        '--interactive',
87
        action='store_true',
88
        default=False,
89
        help='Start an interactive Python shell',
90
    )
91
92
    parser.add_argument(
93
        'scriptname',
94
        nargs='?',
95
        metavar="SCRIPT",
96
        help='Path to script to be preloaded (example: myscript.gmp)',
97
    )
98
    parser.add_argument(
99
        'scriptargs',
100
        nargs='*',
101
        metavar="ARG",
102
        help='Arguments for preloaded script',
103
    )
104
105
    args = parser.parse_args()
106
107
    if 'socket' in args.connection_type and args.sockpath:
108
        print(
109
            'The --sockpath parameter has been deprecated. Please use '
110
            '--socketpath instead',
111
            file=sys.stderr,
112
        )
113
114
    connection = create_connection(**vars(args))
115
116
    transform = EtreeCheckCommandTransform()
117
118
    global_vars = {
119
        'help': Help(),
120
        '__version__': __version__,
121
        '__api_version__': __api_version__,
122
    }
123
124
    username = None
125
    password = None
126
127
    if args.protocol == PROTOCOL_OSP:
128
        protocol_class = Osp
129
        name = 'osp'
130
    else:
131
        protocol_class = Gmp
132
        name = 'gmp'
133
134
    with protocol_class(connection, transform=transform) as protocol:
135
        global_vars[name] = protocol
136
        global_vars['__name__'] = '__{}__'.format(name)
137
138
        if args.protocol == PROTOCOL_GMP:
139
            if args.gmp_username:
140
                (username, password) = authenticate(
141
                    protocol,
142
                    username=args.gmp_username,
143
                    password=args.gmp_password,
144
                )
145
146
        shell_args = Namespace(username=username, password=password)
147
148
        global_vars['args'] = shell_args
149
150
        with_script = args.scriptname and len(args.scriptname) > 0
151
152
        if with_script:
153
            argv = [os.path.abspath(args.scriptname), *args.scriptargs]
154
            shell_args.argv = argv
155
            # for backwards compatibility we add script here
156
            shell_args.script = argv
157
158
        no_script_no_interactive = not args.interactive and not with_script
159
        script_and_interactive = args.interactive and with_script
160
        only_interactive = not with_script and args.interactive
161
        only_script = not args.interactive and with_script
162
163
        if only_interactive or no_script_no_interactive:
164
            enter_interactive_mode(global_vars)
165
166
        if script_and_interactive or only_script:
167
            if only_script:
168
                print(
169
                    'Using gvm-pyshell for running scripts only is deprecated. '
170
                    'Please use gvm-script instead',
171
                    file=sys.stderr,
172
                )
173
174
            script_name = args.scriptname
175
            run_script(script_name, global_vars)
176
177
            if not only_script:
178
                enter_interactive_mode(global_vars)
179
180
181
def enter_interactive_mode(global_vars):
182
    code.interact(
183
        banner='GVM Interactive Console {} API {}. Type "help" to get '
184
        'information about functionality.'.format(__version__, __api_version__),
185
        local=dict(global_vars),
186
    )
187
188
189
if __name__ == '__main__':
190
    main()
191