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

WenjieDu / PyPOTS / 4739569617

pending completion
4739569617

push

github

Wenjie Du
feat: don't limit to install torch-cpu;

2851 of 3498 relevant lines covered (81.5%)

0.82 hits per line

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

0.0
/pypots/utils/commands/doc.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 import BaseCommand
×
13
from pypots.utils.logging import logger
×
14
from tsdb.data_processing import _download_and_extract
×
15

16
CLONED_LATEST_PYPOTS = "temp_pypots_latest"
×
17

18
# These files need to be updated while generating the new documentation
19
DOC_RST_FILES = [
×
20
    "pypots.rst",
21
    "pypots.imputation.rst",
22
    "pypots.classification.rst",
23
    "pypots.clustering.rst",
24
    "pypots.forecasting.rst",
25
    "pypots.data.rst",
26
    "pypots.utils.rst",
27
]
28

29
IMPORT_ERROR_MESSAGE = (
×
30
    "`pypots-cli doc` command is for PyPOTS developers to build documentation easily. "
31
    "Therefore, you need a complete PyPOTS development environment. However, you are missing some dependencies. "
32
    "Please refer to https://github.com/WenjieDu/PyPOTS/blob/main/environment-dev.yml for dependency details. "
33
)
34

35

36
def doc_command_factory(args: Namespace):
×
37
    return DocCommand(
×
38
        args.gene_rst,
39
        args.branch,
40
        args.gene_html,
41
        args.view_doc,
42
        args.port,
43
        args.cleanup,
44
    )
45

46

47
def purge_statics():
×
48
    logger.info(
×
49
        f"Directories _build, _static, and _templates, and {CLONED_LATEST_PYPOTS} will be deleted if exist"
50
    )
51
    shutil.rmtree("_build", ignore_errors=True)
×
52
    shutil.rmtree(CLONED_LATEST_PYPOTS, ignore_errors=True)
×
53
    shutil.rmtree("_static", ignore_errors=True)
×
54
    shutil.rmtree("_templates", ignore_errors=True)
×
55

56

57
class DocCommand(BaseCommand):
×
58
    """CLI tools helping build PyPOTS documentation.
59

60
    Notes
61
    -----
62
    Only code pushed to GitHub can be used for documentation generation.
63
    During generation, PyPOTS repo on GitHub will firstly be cloned to local with the branch specified by
64
    argument `--branch`. The generated rst files will replace the old ones directly. To view the updated
65
    documentation, use option `--view_doc` to generate the doc into HTMLs and deploy it locally for view.
66
    After running `--view_doc`, the generated static files won't be deleted automatically. To purge them,
67
    run the command with option `--cleanup`.
68

69
    Examples
70
    --------
71
    $ pypots-cli doc --gene_rst [--branch main]
72
    $ pypots-cli doc --view_doc [--port 9075]
73
    $ pypots-cli doc --cleanup
74

75
    """
76

77
    @staticmethod
×
78
    def register_subcommand(parser: ArgumentParser):
×
79
        sub_parser = parser.add_parser(
×
80
            "doc", help="CLI tools helping build PyPOTS documentation"
81
        )
82

83
        sub_parser.add_argument(
×
84
            "--gene_rst",
85
            dest="gene_rst",
86
            action="store_true",
87
            help="Generate rst (reStructuredText) documentation according to the latest code on Github",
88
        )
89
        sub_parser.add_argument(
×
90
            "--branch",
91
            type=str,
92
            default="main",
93
            choices=["main", "dev"],
94
            help="Code on which branch will be used for documentation generating",
95
        )
96
        sub_parser.add_argument(
×
97
            "--gene_html",
98
            dest="gene_html",
99
            action="store_true",
100
            help="Generate the sphinx documentation into static HTML files",
101
        )
102
        sub_parser.add_argument(
×
103
            "--view_doc",
104
            dest="view_doc",
105
            action="store_true",
106
            help="Deploy the generated HTML documentation locally for view",
107
        )
108
        sub_parser.add_argument(
×
109
            "--port",
110
            type=int,
111
            default=9075,
112
            help="Use which port to deploy the web server for doc view",  # 9075 looks like "POTS", so use it as default
113
        )
114
        sub_parser.add_argument(
×
115
            "--cleanup",
116
            dest="cleanup",
117
            action="store_true",
118
            help="Delete all caches and static resources like HTML and CSS files ",
119
        )
120

121
        sub_parser.set_defaults(func=doc_command_factory)
×
122

123
    def __init__(
×
124
        self,
125
        gene_rst: bool,
126
        branch: str,
127
        gene_html: bool,
128
        view_doc: bool,
129
        port: int,
130
        cleanup: bool,
131
    ):
132
        self._gene_rst = gene_rst
×
133
        self._branch = branch
×
134
        self._gene_html = gene_html
×
135
        self._view_doc = view_doc
×
136
        self._port = port
×
137
        self._cleanup = cleanup
×
138

139
    def check_arguments(self):
×
140
        """Run some checks on the arguments to avoid error usages"""
141
        parent_dir = os.path.join(".", "..")
×
142
        containing_figs = "figs" in os.listdir(".")
×
143
        pypots_in_the_parent_dir = "pypots" in os.listdir(parent_dir)
×
144
        # if currently under dir 'docs', it should have sub-dir 'figs', and 'pypots' should be in the parent dir
145
        whether_under_dir_docs = containing_figs and pypots_in_the_parent_dir
×
146
        # `pypots-cli dev` should only be run under dir 'docs'
147
        # because we probably will compile the doc and generate HTMLs with command `make`
148
        assert whether_under_dir_docs, (
×
149
            "Command `pypots-cli doc` can only be run under the directory 'docs' in project PyPOTS, "
150
            f"but you're running it under the path {os.getcwd()}. Please make a check."
151
        )
152

153
        if self._cleanup:
×
154
            assert not self._gene_rst and not self._gene_html and not self._view_doc, (
×
155
                "Argument `--cleanup` should be used alone. "
156
                "Try `pypots-cli doc --cleanup`"
157
            )
158

159
    def run(self):
×
160
        """Execute the given command."""
161

162
        # check arguments first
163
        self.check_arguments()
×
164

165
        try:
×
166
            if self._cleanup:
×
167
                logger.info("Purging static files...")
×
168
                purge_statics()
×
169
                logger.info("Purging finished successfully.")
×
170

171
            if self._gene_rst:
×
172
                if os.path.exists(CLONED_LATEST_PYPOTS):
×
173
                    logger.info(
×
174
                        f"Directory {CLONED_LATEST_PYPOTS} exists, deleting it..."
175
                    )
176
                    shutil.rmtree(CLONED_LATEST_PYPOTS, ignore_errors=True)
×
177

178
                # Download the latest code from GitHub
179
                logger.info(
×
180
                    f"Downloading PyPOTS with the latest code on branch '{self._branch}' "
181
                    f"from GitHub into {CLONED_LATEST_PYPOTS}..."
182
                )
183
                url = f"https://github.com/WenjieDu/PyPOTS/archive/refs/heads/{self._branch}.zip"
×
184
                _download_and_extract(url=url, saving_path=CLONED_LATEST_PYPOTS)
×
185

186
                code_dir = f"{CLONED_LATEST_PYPOTS}/PyPOTS-{self._branch}"
×
187
                files_to_move = os.listdir(code_dir)
×
188
                destination_dir = os.path.join(os.getcwd(), CLONED_LATEST_PYPOTS)
×
189
                for f_ in files_to_move:
×
190
                    shutil.move(os.path.join(code_dir, f_), destination_dir)
×
191
                # delete code in tests because we don't need its doc
192
                shutil.rmtree(
×
193
                    f"{CLONED_LATEST_PYPOTS}/pypots/tests", ignore_errors=True
194
                )
195

196
                # Generate the docs according to the cloned code
197
                logger.info("Generating rst files...")
×
198
                self.execute_command(
×
199
                    "SPHINX_APIDOC_OPTIONS=members,undoc-members,show-inheritance,inherited-members "
200
                    f"sphinx-apidoc {CLONED_LATEST_PYPOTS} -o {CLONED_LATEST_PYPOTS}/rst"
201
                )
202

203
                # Only save the files we need.
204
                logger.info("Updating the old documentation...")
×
205
                for f_ in DOC_RST_FILES:
×
206
                    file_to_copy = f"{CLONED_LATEST_PYPOTS}/rst/{f_}"
×
207
                    shutil.copy(file_to_copy, ".")
×
208

209
                # Delete the useless files.
210
                shutil.rmtree(f"{CLONED_LATEST_PYPOTS}", ignore_errors=True)
×
211

212
            if self._gene_html:
×
213
                logger.info("Generating static HTML files...")
×
214
                purge_statics()
×
215
                self.execute_command("make html")
×
216

217
            if self._view_doc:
×
218
                assert os.path.exists(
×
219
                    "_build/html"
220
                ), "_build/html does not exists, please run `pypots-cli doc --gene_html` first"
221
                logger.info(f"Deploying HTML to http://127.0.0.1:{self._port}...")
×
222
                self.execute_command(
×
223
                    f"python -m http.server {self._port} -d _build/html -b 127.0.0.1"
224
                )
225

226
        except ImportError:
×
227
            raise ImportError(IMPORT_ERROR_MESSAGE)
×
228
        except Exception as e:
×
229
            raise RuntimeError(e)
×
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