backuppc_clone.command.BaseCommand   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 115
Duplicated Lines 87.83 %

Importance

Changes 0
Metric Value
eloc 53
dl 101
loc 115
rs 10
c 0
b 0
f 0
wmc 13

7 Methods

Rating   Name   Duplication   Size   Complexity  
A BaseCommand.handle() 16 16 2
A BaseCommand.__init__() 8 8 1
A BaseCommand.__validate_user() 8 8 2
A BaseCommand._handle_command() 8 8 1
A BaseCommand._init_singletons() 6 6 1
A BaseCommand.ask() 17 17 3
A BaseCommand.__validate_config() 18 18 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
import abc
2
import configparser
3
import os
4
from typing import Optional
5
6
from cleo import Command
7
8
from backuppc_clone.Config import Config
9
from backuppc_clone.DataLayer import DataLayer
10
from backuppc_clone.exception.BackupPcCloneException import BackupPcCloneException
11
from backuppc_clone.style.BackupPcCloneStyle import BackupPcCloneStyle
12
13
14 View Code Duplication
class BaseCommand(Command, metaclass=abc.ABCMeta):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
15
    """
16
    Abstract parent command for (almost) all BackupPC Clone commands.
17
    """
18
19
    # ------------------------------------------------------------------------------------------------------------------
20
    def __init__(self, name: Optional[str] = None) -> None:
21
        """
22
        Object constructor.
23
        """
24
        Command.__init__(self, name)
25
26
        self._io: Optional[BackupPcCloneStyle] = None
27
        """
28
        The output style.
29
        """
30
31
    # ------------------------------------------------------------------------------------------------------------------
32
    def __validate_user(self) -> None:
33
        """
34
        Validates that this command is not run under root.
35
        """
36
        self._io.log_very_verbose('testing user')
37
38
        if os.getuid() == 0:
39
            raise BackupPcCloneException('Will not run this command under root')
40
41
    # ------------------------------------------------------------------------------------------------------------------
42
    def __validate_config(self) -> None:
43
        """
44
        Validates the configuration files.
45
        """
46
        if self.input.has_argument('clone.cfg'):
47
            self._io.log_very_verbose('validation configuration')
48
49
            config_filename_clone = self.input.get_argument('clone.cfg')
50
            config_clone = configparser.ConfigParser()
51
            config_clone.read(config_filename_clone)
52
53
            config_original = configparser.ConfigParser()
54
            config_original.read(config_clone['Original']['config'])
55
56
            if config_clone['Original']['name'] != config_original['BackupPC Clone']['name']:
57
                raise BackupPcCloneException(
58
                        'Clone {} is not a clone of original {}'.format(config_clone['Original']['name'],
59
                                                                        config_original['BackupPC Clone']['name']))
60
61
    # ------------------------------------------------------------------------------------------------------------------
62
    def ask(self, question: str, default: Optional[str] = None) -> Optional[str]:
63
        """
64
        Prompt the user for input.
65
66
        @param str question: The question to ask
67
        @param str|None default: The default value
68
69
        :rtype: str|None
70
        """
71
        if default is not None:
72
            question = question + ' [' + default + ']'
73
74
        answer = self._io.ask(question, default)
75
        if answer is None:
76
            answer = default
77
78
        return answer
79
80
    # ------------------------------------------------------------------------------------------------------------------
81
    def _init_singletons(self) -> None:
82
        """
83
        Initializes the singleton objects.
84
        """
85
        Config(self.argument('clone.cfg'))
86
        DataLayer(os.path.join(Config.instance.top_dir_clone, 'clone.db'))
87
88
    # ------------------------------------------------------------------------------------------------------------------
89
    @abc.abstractmethod
90
    def _handle_command(self) -> int:
91
        """
92
        Executes the command.
93
94
        :rtype: int
95
        """
96
        raise NotImplementedError()
97
98
    # ------------------------------------------------------------------------------------------------------------------
99
    def handle(self) -> int:
100
        """
101
        Executes the command.
102
        """
103
        try:
104
            self._io = BackupPcCloneStyle(self.input, self.output)
105
106
            self.__validate_user()
107
            self.__validate_config()
108
            self._init_singletons()
109
110
            return self._handle_command()
111
112
        except BackupPcCloneException as error:
113
            self._io.error(str(error))
114
            return -1
115
116
# ----------------------------------------------------------------------------------------------------------------------
117