pyclean.cli.init_logging()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
# SPDX-FileCopyrightText: 2019 Peter Bittner <[email protected]>
2
#
3
# SPDX-License-Identifier: GPL-3.0-or-later
4
5
"""
6
Command line interface implementation for pyclean.
7
"""
8
9
import argparse
10
import logging
11
12
from . import __version__, modern
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', '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
        '-i',
50
        '--ignore',
51
        metavar='DIRECTORY',
52
        action='extend',
53
        nargs='+',
54
        default=ignore_default_items,
55
        help='directory that should be ignored (may be specified multiple times;'
56
        ' default: %s)' % ' '.join(ignore_default_items),
57
    )
58
    parser.add_argument(
59
        '-d',
60
        '--debris',
61
        metavar='TOPIC',
62
        action='extend',
63
        nargs='*',
64
        default=argparse.SUPPRESS,
65
        choices=debris_choices,
66
        help='remove leftovers from popular Python development tools'
67
        ' (may be specified multiple times; optional: all %s; default: %s)'
68
        % (
69
            ' '.join(debris_optional_topics),
70
            ' '.join(debris_default_topics),
71
        ),
72
    )
73
    parser.add_argument(
74
        '-e',
75
        '--erase',
76
        metavar='PATTERN',
77
        action='extend',
78
        nargs='+',
79
        default=[],
80
        help='delete files or folders matching a globbing pattern (may be specified'
81
        ' multiple times); this will be interactive unless --yes is used.',
82
    )
83
    parser.add_argument(
84
        '-n',
85
        '--dry-run',
86
        action='store_true',
87
        help='show what would be done',
88
    )
89
90
    verbosity = parser.add_mutually_exclusive_group()
91
    verbosity.add_argument('-q', '--quiet', action='store_true', help='be quiet')
92
    verbosity.add_argument(
93
        '-v',
94
        '--verbose',
95
        action='store_true',
96
        help='be more verbose',
97
    )
98
99
    parser.add_argument(
100
        '-y',
101
        '--yes',
102
        action='store_true',
103
        help='assume yes as answer for interactive questions',
104
    )
105
106
    args = parser.parse_args()
107
    init_logging(args)
108
109
    if args.yes and not args.erase:
110
        parser.error('Specifying --yes only makes sense with --erase.')
111
112
    if 'debris' in args:
113
        if 'all' in args.debris:
114
            args.debris = debris_default_topics + debris_optional_topics
115
        elif not args.debris:
116
            args.debris = debris_default_topics
117
        log.debug('Debris topics to scan for: %s', ' '.join(args.debris))
118
    else:
119
        args.debris = []
120
121
    log.debug('Ignored directories: %s', ' '.join(args.ignore))
122
123
    return args
124
125
126
def init_logging(args):
127
    """
128
    Set the log level according to the -v/-q command line options.
129
    """
130
    log_level = (
131
        logging.FATAL if args.quiet else logging.DEBUG if args.verbose else logging.INFO
132
    )
133
    log_format = '%(message)s'
134
    logging.basicConfig(level=log_level, format=log_format)
135
136
137
def main():
138
    """
139
    Entry point for CLI application.
140
    """
141
    args = parse_arguments()
142
143
    try:
144
        modern.pyclean(args)
145
    except Exception as err:
146
        raise SystemExit(err)
147