• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

WenjieDu / PyPOTS / 4755049409

pending completion
4755049409

push

github

GitHub
Merge pull request #63 from WenjieDu/dev

61 of 61 new or added lines in 5 files covered. (100.0%)

2832 of 3490 relevant lines covered (81.15%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pypots/utils/commands/dev.py
1
"""
2
CLI tools to help the development team build PyPOTS.
3
"""
4

5
# Created by Wenjie Du <wenjay.du@gmail.com>
6
# License: GLP-v3
7

8
import os
×
9
import shutil
×
10
from argparse import ArgumentParser, Namespace
×
11

12
from pypots.utils.commands.base import BaseCommand
×
13
from pypots.utils.logging import logger
×
14

15
IMPORT_ERROR_MESSAGE = (
×
16
    "`pypots-cli dev` command is for PyPOTS developers to run tests easily. "
17
    "Therefore, you need a complete PyPOTS development environment. However, you are missing some dependencies. "
18
    "Please refer to https://github.com/WenjieDu/PyPOTS/blob/main/environment-dev.yml for dependency details. "
19
)
20

21

22
def dev_command_factory(args: Namespace):
×
23
    return DevCommand(
×
24
        args.build,
25
        args.cleanup,
26
        args.run_tests,
27
        args.k,
28
        args.show_coverage,
29
        args.lint_code,
30
    )
31

32

33
class DevCommand(BaseCommand):
×
34
    """CLI tools helping develop PyPOTS. Easy the running of tests and code linting with Black and Flake8.
35

36
    Examples
37
    --------
38
    $ pypots-cli dev --run_tests
39
    $ pypots-cli dev --run_tests --show_coverage  # show code coverage
40
    $ pypots-cli dev --run_tests -k imputation  # only run tests cases of imputation models
41
    $ pypots-cli dev --lint_code  # use Black to reformat the code and apply Flake8 to lint code
42

43
    """
44

45
    @staticmethod
×
46
    def register_subcommand(parser: ArgumentParser):
×
47
        sub_parser = parser.add_parser(
×
48
            "dev", help="CLI tools helping develop PyPOTS code"
49
        )
50
        sub_parser.add_argument(
×
51
            "--build",
52
            dest="build",
53
            action="store_true",
54
            help="Build PyPOTS into a wheel and package the source code into a .tar.gz file for distribution",
55
        )
56
        sub_parser.add_argument(
×
57
            "--cleanup",
58
            dest="cleanup",
59
            action="store_true",
60
            help="Delete all caches and building files",
61
        )
62
        sub_parser.add_argument(
×
63
            "--run_tests",
64
            dest="run_tests",
65
            action="store_true",
66
            help="Run all test cases",
67
        )
68
        sub_parser.add_argument(
×
69
            "--show_coverage",
70
            dest="show_coverage",
71
            action="store_true",
72
            help="Show the code coverage report after running tests",
73
        )
74
        sub_parser.add_argument(
×
75
            "-k",
76
            type=str,
77
            default=None,
78
            help="The -k option of pytest. Description of -k option in pytest: "
79
            "only run tests which match the given substring expression. An expression is a python evaluatable "
80
            "expression where all names are substring-matched against test names and their parent classes. "
81
            "Example: -k 'test_method or test_other' matches all test functions and classes whose name contains "
82
            "'test_method' or 'test_other', while -k 'not test_method' matches those that don't contain "
83
            "'test_method' in their names. -k 'not test_method and not test_other' will eliminate the matches. "
84
            "Additionally keywords are matched to classes and functions containing extra names in their "
85
            "'extra_keyword_matches' set, as well as functions which have names assigned directly to them. The "
86
            "matching is case-insensitive.",
87
        )
88
        sub_parser.add_argument(
×
89
            "--lint_code",
90
            dest="lint_code",
91
            action="store_true",
92
            help="Run Black and Flake8 to lint code",
93
        )
94
        sub_parser.set_defaults(func=dev_command_factory)
×
95

96
    def __init__(
×
97
        self,
98
        build: bool,
99
        cleanup: bool,
100
        run_tests: bool,
101
        k: str,
102
        show_coverage: bool,
103
        lint_code: bool,
104
    ):
105
        self._build = build
×
106
        self._cleanup = cleanup
×
107
        self._run_tests = run_tests
×
108
        self._k = k
×
109
        self._show_coverage = show_coverage
×
110
        self._lint_code = lint_code
×
111

112
    def check_arguments(self):
×
113
        """Run some checks on the arguments to avoid error usages"""
114
        self.check_if_under_root_dir()
×
115

116
        if self._k is not None:
×
117
            assert self._run_tests, (
×
118
                "Argument `-k` should combine the use of `--run_tests`. "
119
                "Try `pypots-cli dev --run_tests -k your_pattern`"
120
            )
121

122
        if self._show_coverage:
×
123
            assert self._run_tests, (
×
124
                "Argument `--show_coverage` should combine the use of `--run_tests`. "
125
                "Try `pypots-cli dev --run_tests --show_coverage`"
126
            )
127

128
        if self._cleanup:
×
129
            assert not self._run_tests and not self._lint_code, (
×
130
                "Argument `--cleanup` should be used alone. "
131
                "Try `pypots-cli dev --cleanup`"
132
            )
133

134
    def run(self):
×
135
        """Execute the given command."""
136

137
        # check arguments first
138
        self.check_arguments()
×
139

140
        try:
×
141
            if self._cleanup:
×
142
                shutil.rmtree("build", ignore_errors=True)
×
143
                shutil.rmtree("dist", ignore_errors=True)
×
144
                shutil.rmtree("pypots.egg-info", ignore_errors=True)
×
145
            elif self._build:
×
146
                self.execute_command("python setup.py sdist bdist bdist_wheel")
×
147
            elif self._run_tests:
×
148
                pytest_command = f"pytest -k {self._k}" if self._k else "pytest"
×
149
                command_to_run_test = (
×
150
                    f"coverage run -m {pytest_command}"
151
                    if self._show_coverage
152
                    else pytest_command
153
                )
154
                logger.info(f"Executing '{command_to_run_test}'...")
×
155
                self.execute_command(command_to_run_test)
×
156
                if self._show_coverage:
×
157
                    self.execute_command("coverage report -m")
×
158
            elif self._lint_code:
×
159
                logger.info("Reformatting with Black...")
×
160
                self.execute_command("black .")
×
161
                logger.info("Linting with Flake8...")
×
162
                self.execute_command("flake8 .")
×
163
        except ImportError:
×
164
            raise ImportError(IMPORT_ERROR_MESSAGE)
×
165
        except Exception as e:
×
166
            raise RuntimeError(e)
×
167
        finally:
168
            shutil.rmtree(".pytest_cache", ignore_errors=True)
×
169
            if os.path.exists(".coverage"):
×
170
                os.remove(".coverage")
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc