Completed
Pull Request — master (#2185)
by Zatreanu
01:53
created

PackageRequirement.multiple()   B

Complexity

Conditions 5

Size

Total Lines 66

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
c 1
b 0
f 0
dl 0
loc 66
rs 8.2487

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
from coala_decorators.decorators import generate_eq, generate_repr
2
3
4
@generate_eq("manager", "package", "version")
5
@generate_repr()
6
class PackageRequirement:
7
    """
8
    This class helps keeping track of bear requirements. It should simply
9
    be appended to the REQUIREMENTS tuple inside the Bear class.
10
11
    Two ``PackageRequirements`` should always be equal if they have the same
12
    manager, package and version:
13
14
    >>> pr1 = PackageRequirement('pip', 'coala_decorators', '0.1.0')
15
    >>> pr2 = PackageRequirement('pip', 'coala_decorators', '0.1.0')
16
    >>> pr1 == pr2
17
    True
18
    """
19
20
    def __init__(self, manager: str, package: str, version=""):
21
        """
22
        Constructs a new ``PackageRequirement``.
23
24
        >>> pr = PackageRequirement('pip', 'colorama', '0.1.0')
25
        >>> pr.manager
26
        'pip'
27
        >>> pr.package
28
        'colorama'
29
        >>> pr.version
30
        '0.1.0'
31
32
        :param manager: A string with the name of the manager (pip, npm, etc).
33
        :param package: A string with the name of the package to be installed.
34
        :param version: A version string. Leave empty to specify latest version.
35
        """
36
        self.manager = manager
37
        self.package = package
38
        self.version = version
39
40
    def check(self):
41
        """
42
        Check if the requirement is satisfied.
43
44
        >>> PackageRequirement('pip', 'coala_decorators', '0.2.1').check()
45
        Traceback (most recent call last):
46
        ...
47
        NotImplementedError
48
49
        :return: Returns True if satisfied, False if not.
50
        """
51
        raise NotImplementedError
52
53
    @classmethod
54
    def multiple(cls, *args):
55
        """
56
        Creates a tuple of multiple instances of a class.
57
58
        Should not be instances of ``PackageRequirement``, as this is an
59
        abstract class:
60
61
        >>> PackageRequirement.multiple(('pip', 'coala_decorators', '0.1.0'),)
62
        Traceback (most recent call last):
63
        ...
64
        NotImplementedError
65
66
        It can only be used for requirements of the same manager. For example,
67
        consider a manager ``XYZRequirement`` that inherits from
68
        PackageRequirement. This subclass will have the manager set to XYZ:
69
70
        >>> class XYZRequirement(PackageRequirement): pass
71
72
        This is the case where you would provide strings only, to specify the
73
        latest version automatically:
74
75
        >>> REQUIREMENTS = XYZRequirement.multiple(
76
        ...     'package1', 'package2')
77
78
        And if you choose to mix them, specifying version for some and for some
79
        not:
80
81
        >>> REQUIREMENTS = XYZRequirement.multiple(
82
        ...     'package1', ('package2', '2.0'))
83
84
        Lists are also valid arguments:
85
86
        >>> REQUIREMENTS = XYZRequirement.multiple(
87
        ...     ['package1', '1.0'],)
88
89
        In case you provide too many arguments into the tuple, an error will be
90
        raised:
91
92
        >>> REQUIREMENTS = XYZRequirement.multiple(
93
        ...     'package1', ('package2', '2.0', '# some comment'))
94
        Traceback (most recent call last):
95
        ...
96
        TypeError: Too many elements provided.
97
98
        :param args:       In the subclasses, the ``manager`` is already
99
                           specified, so they hould be iterables with two
100
                           elements: ``('packageName', 'version')`` or strings:
101
                           ``'packageName'`` if latest version is wanted.
102
        :return:           A tuple containing instances of the subclass.
103
        :raises TypeError: In case the iterables contain more than two
104
                           elements.
105
        """
106
        if cls == PackageRequirement:
107
            raise NotImplementedError
108
        else:
109
            reqs = []
110
            for requirement in args:
111
                if isinstance(requirement, str):
112
                    reqs.append(cls(requirement))
113
                elif len(requirement) == 2:
114
                    name, version = requirement
115
                    reqs.append(cls(name, version))
116
                else:
117
                    raise TypeError('Too many elements provided.')
118
            return tuple(reqs)
119