setup   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 97
dl 0
loc 163
rs 10
c 0
b 0
f 0
wmc 15

11 Methods

Rating   Name   Duplication   Size   Complexity  
A TestCommand.finalize_options() 0 3 1
A Cleaner.run() 0 3 1
A TestCommand.get_args() 0 5 2
A SimpleCommand.run() 0 3 1
A SimpleCommand.finalize_options() 0 2 1
A SimpleCommand.__init__() 0 5 1
A Test.run() 0 9 2
A TestCommand.initialize_options() 0 3 1
A SimpleCommand.initialize_options() 0 2 1
A TestCoverage.run() 0 10 2
A Linter.run() 0 9 2
1
"""Setup script.
2
3
Run "python3 setup --help-commands" to list all available commands and their
4
descriptions.
5
"""
6
import re
7
import sys
8
from abc import abstractmethod
9
# Disabling checks due to https://github.com/PyCQA/pylint/issues/73
10
from subprocess import CalledProcessError, call, check_call
11
12
from setuptools import Command, find_packages, setup
13
14
15
class SimpleCommand(Command):
16
    """Make Command implementation simpler."""
17
18
    user_options = []
19
20
    def __init__(self, *args, **kwargs):
21
        """Store arguments so it's possible to call other commands later."""
22
        super().__init__(*args, **kwargs)
23
        self._args = args
24
        self._kwargs = kwargs
25
26
    @abstractmethod
27
    def run(self):
28
        """Run when command is invoked.
29
30
        Use *call* instead of *check_call* to ignore failures.
31
        """
32
33
    def initialize_options(self):
34
        """Set default values for options."""
35
36
    def finalize_options(self):
37
        """Post-process options."""
38
39
40
# pylint: disable=attribute-defined-outside-init, abstract-method
41
class TestCommand(Command):
42
    """Test tags decorators."""
43
44
    user_options = [
45
        ("k=", None, "Specify a pytest -k expression."),
46
    ]
47
48
    def get_args(self):
49
        """Return args to be used in test command."""
50
        if self.k:
51
            return f"-k '{self.k}'"
52
        return ""
53
54
    def initialize_options(self):
55
        """Set default size and type args."""
56
        self.k = ""
57
58
    def finalize_options(self):
59
        """Post-process."""
60
        pass
61
62
63
class Cleaner(SimpleCommand):
64
    """Custom clean command to tidy up the project root."""
65
66
    description = 'clean build, dist, pyc and egg from package and docs'
67
68
    def run(self):
69
        """Clean build, dist, pyc and egg from package and docs."""
70
        call('make clean', shell=True)
71
72
73
class Test(TestCommand):
74
    """Run all tests."""
75
76
    description = "run tests and display results"
77
78
    def run(self):
79
        """Run tests."""
80
        cmd = f"python3 -m pytest tests/ {self.get_args()}"
81
        try:
82
            check_call(cmd, shell=True)
83
        except CalledProcessError as exc:
84
            print(exc)
85
            print('Unit tests failed. Fix the errors above and try again.')
86
            sys.exit(-1)
87
88
89
class TestCoverage(Test):
90
    """Display test coverage."""
91
92
    description = "run tests and display code coverage"
93
94
    def run(self):
95
        """Run tests quietly and display coverage report."""
96
        cmd = "python3 -m pytest --cov=. tests/ --cov-report term-missing"
97
        cmd += f" {self.get_args()}"
98
        try:
99
            check_call(cmd, shell=True)
100
        except CalledProcessError as exc:
101
            print(exc)
102
            print('Coverage tests failed. Fix the errors above and try again.')
103
            sys.exit(-1)
104
105
106
class Linter(SimpleCommand):
107
    """Code linters."""
108
109
    description = 'lint Python source code'
110
111
    def run(self):
112
        """Run yala."""
113
        print('Yala is running. It may take several seconds...')
114
        try:
115
            check_call('yala setup.py tests kytos', shell=True)
116
            print('No linter error found.')
117
        except CalledProcessError:
118
            print('Linter check failed. Fix the error(s) above and try again.')
119
            sys.exit(-1)
120
121
122
# We are parsing the metadata file as if it was a text file because if we
123
# import it as a python module, necessarily the kytos.utils module would be
124
# initialized.
125
META_FILE = open("kytos/utils/metadata.py").read()
126
METADATA = dict(re.findall(r"(__[a-z]+__)\s*=\s*'([^']+)'", META_FILE))
127
128
setup(name='kytos-utils',
129
      version=METADATA.get('__version__'),
130
      description=METADATA.get('__description__'),
131
      long_description=open("README.rst", "r").read(),
132
      url=METADATA.get('__url__'),
133
      author=METADATA.get('__author__'),
134
      author_email=METADATA.get('__author_email__'),
135
      license=METADATA.get('__license__'),
136
      test_suite='tests',
137
      include_package_data=True,
138
      scripts=['bin/kytos'],
139
      install_requires=[line.strip()
140
                        for line in open("requirements/run.txt").readlines()
141
                        if not line.startswith('#')],
142
      extras_require={'dev': [
143
          'pip-tools >= 2.0',
144
          'pytest==8.0.1',
145
          'pytest-cov==4.1.0',
146
          'pytest-asyncio==0.23.5',
147
          'black==24.2.0',
148
          'isort==5.13.2',
149
          'pylint==3.1.0',
150
          'pycodestyle==2.11.1',
151
          'yala==3.2.0',
152
          'tox==4.13.0',
153
          'virtualenv==20.25.1',
154
      ]},
155
      packages=find_packages(exclude=['tests']),
156
      cmdclass={
157
          'clean': Cleaner,
158
          'coverage': TestCoverage,
159
          'lint': Linter,
160
          'test': Test
161
      },
162
      zip_safe=False)
163