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

WenjieDu / PyPOTS / 12015168636

25 Nov 2024 05:10PM UTC coverage: 84.286% (-0.02%) from 84.307%
12015168636

push

github

web-flow
Update docs for CSAI (#549)

12047 of 14293 relevant lines covered (84.29%)

4.94 hits per line

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

82.28
/pypots/cli/doc.py
1
"""
3✔
2
CLI tools to help the development team build PyPOTS.
3
"""
4

5
# Created by Wenjie Du <wenjay.du@gmail.com>
6
# License: BSD-3-Clause
7

8
import os
6✔
9
import shutil
6✔
10
from argparse import Namespace
6✔
11

12
from tsdb.utils.downloading import _download_and_extract
6✔
13

14
from ..cli.base import BaseCommand
6✔
15
from ..utils.logging import logger
6✔
16

17
CLONED_LATEST_PYPOTS = "temp_pypots_latest"
6✔
18

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

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

36

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

47

48
def purge_temp_files():
6✔
49
    logger.info(f"Directories _build and {CLONED_LATEST_PYPOTS} will be deleted if exist")
6✔
50
    shutil.rmtree("docs/_build", ignore_errors=True)
6✔
51
    shutil.rmtree(CLONED_LATEST_PYPOTS, ignore_errors=True)
6✔
52

53

54
class DocCommand(BaseCommand):
6✔
55
    """CLI tools helping build PyPOTS documentation.
3✔
56

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

66
    Examples
67
    --------
68
    $ pypots-cli doc --gene_rst [--branch main]
69
    $ pypots-cli doc --view_doc [--port 9075]
70
    $ pypots-cli doc --cleanup
71

72
    """
73

74
    @staticmethod
6✔
75
    def register_subcommand(parser):
6✔
76
        sub_parser = parser.add_parser(
×
77
            "doc",
78
            help="CLI tools helping build PyPOTS documentation",
79
            allow_abbrev=True,
80
        )
81

82
        sub_parser.add_argument(
×
83
            "--gene-rst",
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
            "-b",
91
            "--branch",
92
            type=str,
93
            default="main",
94
            choices=["main", "dev"],
95
            help="Code on which branch will be used for documentation generating",
96
        )
97
        sub_parser.add_argument(
×
98
            "--gene-html",
99
            "--gene_html",
100
            dest="gene_html",
101
            action="store_true",
102
            help="Generate the sphinx documentation into static HTML files",
103
        )
104
        sub_parser.add_argument(
×
105
            "--view-doc",
106
            "--view_doc",
107
            dest="view_doc",
108
            action="store_true",
109
            help="Deploy the generated HTML documentation locally for view",
110
        )
111
        sub_parser.add_argument(
×
112
            "-p",
113
            "--port",
114
            type=int,
115
            default=9075,
116
            help="Use which port to deploy the web server for doc view",  # 9075 looks like "POTS", so use it as default
117
        )
118
        sub_parser.add_argument(
×
119
            "-c",
120
            "--cleanup",
121
            dest="cleanup",
122
            action="store_true",
123
            help="Delete all caches and static resources like HTML and CSS files ",
124
        )
125

126
        sub_parser.set_defaults(func=doc_command_factory)
×
127

128
    def __init__(
6✔
129
        self,
130
        gene_rst: bool,
131
        branch: str,
132
        gene_html: bool,
133
        view_doc: bool,
134
        port: int,
135
        cleanup: bool,
136
    ):
137
        self._gene_rst = gene_rst
6✔
138
        self._branch = branch
6✔
139
        self._gene_html = gene_html
6✔
140
        self._view_doc = view_doc
6✔
141
        self._port = port
6✔
142
        self._cleanup = cleanup
6✔
143

144
    def checkup(self):
6✔
145
        """Run some checks on the arguments to avoid error usages"""
146
        self.check_if_under_root_dir(strict=True)
6✔
147

148
        if self._cleanup:
6✔
149
            assert (
6✔
150
                not self._gene_rst and not self._gene_html and not self._view_doc
151
            ), "Argument `--cleanup` should be used alone. Try `pypots-cli doc --cleanup`"
152

153
    def run(self):
6✔
154
        """Execute the given command."""
155
        # run checks first
156
        self.checkup()
6✔
157

158
        try:
6✔
159
            if self._cleanup:
6✔
160
                logger.info("Purging static files...")
6✔
161
                purge_temp_files()
6✔
162
                logger.info("Purging finished successfully.")
6✔
163

164
            if self._gene_rst:
6✔
165
                if os.path.exists(CLONED_LATEST_PYPOTS):
6✔
166
                    logger.info(f"Directory {CLONED_LATEST_PYPOTS} exists, deleting it...")
×
167
                    shutil.rmtree(CLONED_LATEST_PYPOTS, ignore_errors=True)
×
168

169
                # Download the latest code from GitHub
170
                logger.info(
6✔
171
                    f"Downloading PyPOTS with the latest code on branch '{self._branch}' "
172
                    f"from GitHub into {CLONED_LATEST_PYPOTS}..."
173
                )
174
                url = f"https://github.com/WenjieDu/PyPOTS/archive/refs/heads/{self._branch}.zip"
6✔
175
                _download_and_extract(url=url, saving_path=CLONED_LATEST_PYPOTS)
6✔
176

177
                code_dir = f"{CLONED_LATEST_PYPOTS}/PyPOTS-{self._branch}"
6✔
178
                files_to_move = os.listdir(code_dir)
6✔
179
                destination_dir = os.path.join(os.getcwd(), CLONED_LATEST_PYPOTS)
6✔
180
                for f_ in files_to_move:
6✔
181
                    shutil.move(os.path.join(code_dir, f_), destination_dir)
6✔
182
                # delete code in tests because we don't need its doc
183
                shutil.rmtree(f"{CLONED_LATEST_PYPOTS}/pypots/tests", ignore_errors=True)
6✔
184

185
                # Generate the docs according to the cloned code
186
                logger.info("Generating rst files...")
6✔
187
                os.environ["SPHINX_APIDOC_OPTIONS"] = "members,undoc-members,show-inheritance,inherited-members"
6✔
188
                self.execute_command(f"sphinx-apidoc {CLONED_LATEST_PYPOTS} -o {CLONED_LATEST_PYPOTS}/rst")
6✔
189

190
                # Only save the files we need.
191
                logger.info("Updating the old documentation...")
6✔
192
                for f_ in DOC_RST_FILES:
6✔
193
                    file_to_copy = f"{CLONED_LATEST_PYPOTS}/rst/{f_}"
6✔
194
                    shutil.copy(file_to_copy, "docs")
6✔
195

196
                # Delete the useless files.
197
                shutil.rmtree(f"{CLONED_LATEST_PYPOTS}", ignore_errors=True)
6✔
198

199
            if self._gene_html:
6✔
200
                logger.info("Generating static HTML files...")
6✔
201
                purge_temp_files()
6✔
202
                self.execute_command("cd docs && make html")
6✔
203

204
            if self._view_doc:
6✔
205
                assert os.path.exists(
6✔
206
                    "docs/_build/html"
207
                ), "docs/_build/html does not exists, please run `pypots-cli doc --gene_html` first"
208
                logger.info(f"Deploying HTML to http://127.0.0.1:{self._port}...")
6✔
209
                self.execute_command(f"python -m http.server {self._port} -d docs/_build/html -b 127.0.0.1")
6✔
210

211
        except ImportError:
×
212
            raise ImportError(IMPORT_ERROR_MESSAGE)
×
213
        except Exception as e:
×
214
            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