pyclean.cli.parse_arguments()   D
last analyzed

Complexity

Conditions 9

Size

Total Lines 124
Code Lines 93

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 93
dl 0
loc 124
rs 4.8957
c 0
b 0
f 0
cc 9
nop 0

How to fix   Long Method   

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:

1
# SPDX-FileCopyrightText: 2019 Peter Bittner <[email protected]>
2
#
3
# SPDX-License-Identifier: GPL-3.0-or-later
4
5
"""Command line interface implementation for pyclean."""
6
7
import argparse
8
import logging
9
import shutil
10
11
from . import __version__
12
from . import main as main_module
13
14
log = logging.getLogger(__name__)
15
16
17
def parse_arguments():
18
    """
19
    Parse and handle CLI arguments.
20
    """
21
    debris_default_topics = ['cache', 'coverage', 'package', 'pytest', 'ruff']
22
    debris_optional_topics = ['jupyter', 'mypy', 'pyright', 'tox']
23
    debris_choices = ['all', *debris_default_topics, *debris_optional_topics]
24
    ignore_default_items = [
25
        '.git',
26
        '.hg',
27
        '.svn',
28
        '.tox',
29
        '.venv',
30
        'node_modules',
31
        'venv',
32
    ]
33
34
    parser = argparse.ArgumentParser(
35
        description=(
36
            'Remove bytecode files, cache directories, build and test artifacts '
37
            'and other debris in your Python project or elsewhere.'
38
        ),
39
        epilog='Made with ♥ by Painless Software, 🄯 Peter Bittner.',
40
    )
41
42
    parser.add_argument('--version', action='version', version=__version__)
43
    parser.add_argument(
44
        'directory',
45
        nargs='+',
46
        help='directory tree to traverse for bytecode and debris',
47
    )
48
    parser.add_argument(
49
        '-d',
50
        '--debris',
51
        metavar='TOPIC',
52
        action='extend',
53
        nargs='*',
54
        default=argparse.SUPPRESS,
55
        choices=debris_choices,
56
        help='remove leftovers from popular Python development tools'
57
        ' (may be specified multiple times; optional: all %s; default: %s)'
58
        % (
59
            ' '.join(debris_optional_topics),
60
            ' '.join(debris_default_topics),
61
        ),
62
    )
63
    parser.add_argument(
64
        '-e',
65
        '--erase',
66
        metavar='PATTERN',
67
        action='extend',
68
        nargs='+',
69
        default=[],
70
        help='delete files or folders matching a globbing pattern (may be specified'
71
        ' multiple times); this will be interactive unless --yes is used.',
72
    )
73
    parser.add_argument(
74
        '-f',
75
        '--folders',
76
        action='store_true',
77
        help='remove empty directories',
78
    )
79
    parser.add_argument(
80
        '-g',
81
        '--git-clean',
82
        action='store_true',
83
        default=False,
84
        help='run git clean to remove untracked files; this will be interactive'
85
        ' unless --yes is used.',
86
    )
87
    parser.add_argument(
88
        '-i',
89
        '--ignore',
90
        metavar='DIRECTORY',
91
        action='extend',
92
        nargs='+',
93
        default=ignore_default_items,
94
        help='directory that should be ignored (may be specified multiple times;'
95
        ' default: %s)' % ' '.join(ignore_default_items),
96
    )
97
    parser.add_argument(
98
        '-n',
99
        '--dry-run',
100
        action='store_true',
101
        help='show what would be done',
102
    )
103
104
    verbosity = parser.add_mutually_exclusive_group()
105
    verbosity.add_argument('-q', '--quiet', action='store_true', help='be quiet')
106
    verbosity.add_argument(
107
        '-v',
108
        '--verbose',
109
        action='store_true',
110
        help='be more verbose',
111
    )
112
113
    parser.add_argument(
114
        '-y',
115
        '--yes',
116
        action='store_true',
117
        help='assume yes as answer for interactive questions',
118
    )
119
120
    args = parser.parse_args()
121
    init_logging(args)
122
123
    if args.git_clean and not shutil.which('git'):
124
        parser.error('Git is not available. Install Git to use --git-clean.')
125
126
    if args.yes and not args.erase and not args.git_clean:
127
        parser.error('Specifying --yes only makes sense with --erase or --git-clean.')
128
129
    if 'debris' in args:
130
        if 'all' in args.debris:
131
            args.debris = debris_default_topics + debris_optional_topics
132
        elif not args.debris:
133
            args.debris = debris_default_topics
134
        log.debug('Debris topics to scan for: %s', ' '.join(args.debris))
135
    else:
136
        args.debris = []
137
138
    log.debug('Ignored directories: %s', ' '.join(args.ignore))
139
140
    return args
141
142
143
def init_logging(args):
144
    """
145
    Set the log level according to the -v/-q command line options.
146
    """
147
    log_level = (
148
        logging.FATAL if args.quiet else logging.DEBUG if args.verbose else logging.INFO
149
    )
150
    log_format = '%(message)s'
151
    logging.basicConfig(level=log_level, format=log_format)
152
153
154
def main():
155
    """
156
    Entry point for CLI application.
157
    """
158
    args = parse_arguments()
159
160
    try:
161
        main_module.pyclean(args)
162
    except Exception as err:
163
        raise SystemExit(err)
164
    except KeyboardInterrupt:
165
        msg = 'Aborted by user.'
166
        raise SystemExit(msg)
167