Completed
Pull Request — master (#2391)
by Zatreanu
02:06
created

PackageRequirement.upload()   A

Complexity

Conditions 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 0
loc 15
rs 9.4285
1
from coala_decorators.decorators import generate_eq, generate_repr
2
import os
3
4
5
@generate_eq("manager", "package", "version")
6
@generate_repr()
7
class PackageRequirement:
8
    """
9
    This class helps keeping track of bear requirements. It should simply
10
    be appended to the REQUIREMENTS tuple inside the Bear class.
11
12
    Two ``PackageRequirements`` should always be equal if they have the same
13
    manager, package and version:
14
15
    >>> pr1 = PackageRequirement('pip', 'coala_decorators', '0.1.0')
16
    >>> pr2 = PackageRequirement('pip', 'coala_decorators', '0.1.0')
17
    >>> pr1 == pr2
18
    True
19
    """
20
21
    def __init__(self, manager: str, package: str, version=""):
22
        """
23
        Constructs a new ``PackageRequirement``.
24
25
        >>> pr = PackageRequirement('pip', 'colorama', '0.1.0')
26
        >>> pr.manager
27
        'pip'
28
        >>> pr.package
29
        'colorama'
30
        >>> pr.version
31
        '0.1.0'
32
33
        :param manager: A string with the name of the manager (pip, npm, etc).
34
        :param package: A string with the name of the package to be installed.
35
        :param version: A version string. Leave empty to specify latest version.
36
        """
37
        self.manager = manager
38
        self.package = package
39
        self.version = version
40
41
    def check(self):
42
        """
43
        Check if the requirement is satisfied.
44
45
        >>> PackageRequirement('pip', 'coala_decorators', '0.2.1').check()
46
        Traceback (most recent call last):
47
        ...
48
        NotImplementedError
49
50
        :return: Returns True if satisfied, False if not.
51
        """
52
        raise NotImplementedError
53
54
    @classmethod
55
    def multiple(cls, *args):
56
        """
57
        Creates a set of multiple instances of a class.
58
59
        Should not be instances of ``PackageRequirement``, as this is an
60
        abstract class:
61
62
        >>> PackageRequirement.multiple(('pip', 'coala_decorators', '0.1.0'),)
63
        Traceback (most recent call last):
64
        ...
65
        NotImplementedError
66
67
        It can only be used for requirements of the same manager. For example,
68
        consider a manager ``XYZRequirement`` that inherits from
69
        PackageRequirement. This subclass will have the manager set to XYZ:
70
71
        >>> class XYZRequirement(PackageRequirement):
72
        ...     manager = 'xyz'
73
        ...     def __init__(self, package, version=""):
74
        ...         PackageRequirement.__init__(self, package, version)
75
76
        This is the case where you would provide strings only, to specify the
77
        latest version automatically:
78
79
        >>> REQUIREMENTS = XYZRequirement.multiple(
80
        ...     "package1", "package2")
81
82
        And if you choose to mix them, specifying version for some and for some
83
        not:
84
85
        >>> REQUIREMENTS = XYZRequirement.multiple(
86
        ...     'package1', ('package2', '2.0'))
87
88
        Lists are also valid arguments:
89
90
        >>> REQUIREMENTS = XYZRequirement.multiple(
91
        ...     ['package1', '1.0'],)
92
93
        In case you provide too many arguments into the tuple, an error will be
94
        raised:
95
96
        >>> REQUIREMENTS = XYZRequirement.multiple(
97
        ...     'package1', ('package2', '2.0', 'package3'))
98
        Traceback (most recent call last):
99
        ...
100
        TypeError: Too many elements provided.
101
102
        :param args:       In the subclasses, the ``manager`` is already
103
                           specified, so they hould be iterables with two
104
                           elements: ``('packageName', 'version')`` or strings:
105
                           ``'packageName'`` if latest version is wanted.
106
        :return:           A tuple containing instances of the subclass.
107
        :raises TypeError: In case the iterables contain more than two
108
                           elements.
109
        """
110
        if cls == PackageRequirement:
111
            raise NotImplementedError
112
        else:
113
            reqs = []
114
            for requirement in args:
115
                if isinstance(requirement, str):
116
                    reqs.append(cls(requirement))
117
                elif len(requirement) == 2:
118
                    name, version = requirement
119
                    reqs.append(cls(name, version))
120
                else:
121
                    raise TypeError('Too many elements provided.')
122
            return set(reqs)
123
124
    @classmethod
125
    def upload(self):
0 ignored issues
show
Coding Style Best Practice introduced by
The first argument of the class method upload should be named cls.
Loading history...
126
        """
127
        An upload method which uploads a conda package containing the command
128
        to install the corresponding package.
129
        """
130
        name = self.package
131
        if not os.path.exists(name):
132
            os.mkdir(name)
133
        file = open(name + '/' + name + '.py', 'a')
134
        file.write(self.manager + ' ' + self.package)
135
        file.close()
136
        meta = open(name + '/meta.yaml', 'w')
137
        # also create all the scripts here, for windows and OS X
138
        meta.close()
139