Passed
Push — main ( 9b73b1...666399 )
by Peter
01:12
created

pyclean.erase.delete_filesystem_objects()   C

Complexity

Conditions 10

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 34
rs 5.9999
c 0
b 0
f 0
cc 10
nop 4

How to fix   Complexity   

Complexity

Complex classes like pyclean.erase.delete_filesystem_objects() 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
# SPDX-FileCopyrightText: 2020 Peter Bittner <[email protected]>
2
#
3
# SPDX-License-Identifier: GPL-3.0-or-later
4
5
"""Freeform target deletion with interactive prompt."""
6
7
import logging
8
9
from .runner import Runner
10
11
log = logging.getLogger(__name__)
12
13
14
def confirm(message):
15
    """An interactive confirmation prompt."""
16
    try:
17
        answer = input('%s? ' % message)
18
        return answer.strip().lower() in ['y', 'yes']
19
    except KeyboardInterrupt:
20
        msg = 'Aborted by user.'
21
        raise SystemExit(msg)
22
23
24
def delete_filesystem_objects(directory, path_glob, prompt=False, dry_run=False):
25
    """
26
    Identifies all pathnames matching a specific glob pattern, and attempts
27
    to delete them in the proper order, optionally asking for confirmation.
28
29
    Implementation Note: We sort the file system objects in *reverse order*
30
    and first delete *all files* before removing directories. This way we
31
    make sure that the directories that are deepest down in the hierarchy
32
    are empty (for both files & directories) when we attempt to remove them.
33
    """
34
    all_names = sorted(directory.glob(path_glob), reverse=True)
35
    dirs = (name for name in all_names if name.is_dir() and not name.is_symlink())
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable name does not seem to be defined.
Loading history...
36
    files = (name for name in all_names if not name.is_dir() or name.is_symlink())
37
38
    for file_object in files:
39
        file_type = 'symlink' if file_object.is_symlink() else 'file'
40
        if (
41
            not dry_run
42
            and prompt
43
            and not confirm('Delete %s %s' % (file_type, file_object))
44
        ):
45
            Runner.unlink_failed += 1
46
            continue
47
        Runner.unlink(file_object)
48
49
    for dir_object in dirs:
50
        if (
51
            not dry_run
52
            and prompt
53
            and not confirm('Remove empty directory %s' % dir_object)
54
        ):
55
            Runner.rmdir_failed += 1
56
            continue
57
        Runner.rmdir(dir_object)
58
59
60
def remove_freeform_targets(directory, glob_patterns, yes, dry_run=False):
61
    """
62
    Remove free-form targets using globbing.
63
64
    This is **potentially dangerous** since users can delete everything
65
    anywhere in their file system, including the entire project they're
66
    working on. For this reason, the implementation imposes the following
67
    (user experience-related) restrictions:
68
69
    - Deleting (directories) is not recursive, directory contents must be
70
      explicitly specified using globbing (e.g. ``dirname/**/*``).
71
    - The user is responsible for the deletion order, so that a directory
72
      is empty when it is attempted to be deleted.
73
    - A confirmation prompt for the deletion of every single file system
74
      object is shown (unless the ``--yes`` option is used, in addition).
75
    """
76
    for path_glob in glob_patterns:
77
        log.debug('Erase file system objects matching: %s', path_glob)
78
        delete_filesystem_objects(directory, path_glob, prompt=not yes, dry_run=dry_run)
79