mastodown 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mastodown-0.1.0/.github/copilot-instructions.md +28 -0
- mastodown-0.1.0/.gitignore +13 -0
- mastodown-0.1.0/.python-version +1 -0
- mastodown-0.1.0/.readthedocs.yaml +18 -0
- mastodown-0.1.0/LICENSE +21 -0
- mastodown-0.1.0/PKG-INFO +28 -0
- mastodown-0.1.0/README.md +17 -0
- mastodown-0.1.0/docs/Makefile +19 -0
- mastodown-0.1.0/docs/api/index.rst +9 -0
- mastodown-0.1.0/docs/api/mastodown.cli.rst +8 -0
- mastodown-0.1.0/docs/api/mastodown.download.rst +8 -0
- mastodown-0.1.0/docs/api/mastodown.query.rst +8 -0
- mastodown-0.1.0/docs/cli-recipes.md +55 -0
- mastodown-0.1.0/docs/cli-reference.md +127 -0
- mastodown-0.1.0/docs/conf.py +39 -0
- mastodown-0.1.0/docs/generate_api_reference.py +71 -0
- mastodown-0.1.0/docs/generate_cli_reference.py +76 -0
- mastodown-0.1.0/docs/getting-started.md +138 -0
- mastodown-0.1.0/docs/index.md +22 -0
- mastodown-0.1.0/docs/installation.md +65 -0
- mastodown-0.1.0/pyproject.toml +39 -0
- mastodown-0.1.0/sandbox/obs_query.py +32 -0
- mastodown-0.1.0/src/mastodown/__init__.py +1 -0
- mastodown-0.1.0/src/mastodown/_version.py +24 -0
- mastodown-0.1.0/src/mastodown/cli.py +203 -0
- mastodown-0.1.0/src/mastodown/download.py +185 -0
- mastodown-0.1.0/src/mastodown/query.py +116 -0
- mastodown-0.1.0/tests/test_cli.py +260 -0
- mastodown-0.1.0/tests/test_cli_reference.py +26 -0
- mastodown-0.1.0/tests/test_download.py +89 -0
- mastodown-0.1.0/tests/test_query.py +72 -0
- mastodown-0.1.0/uv.lock +1584 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Mastodown Copilot Instructions
|
|
2
|
+
|
|
3
|
+
## Commands
|
|
4
|
+
|
|
5
|
+
- Set up the development environment with `uv sync`.
|
|
6
|
+
- Run all tests with `uv run pytest`.
|
|
7
|
+
- Run one test with `uv run pytest tests/test_query.py::QueryObservationTests::test_query_uses_date_range_filters_and_max_entries`.
|
|
8
|
+
- Build documentation, including generated API and CLI reference pages, with `uv run make -C docs html`. The build treats warnings as errors.
|
|
9
|
+
- Check that the committed CLI reference matches `mastodown --help` with `uv run python docs/generate_cli_reference.py --check`.
|
|
10
|
+
|
|
11
|
+
Python 3.11 or later is required. When using a pip-installed environment rather than uv, omit `uv run`.
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
- The package uses a `src/` layout. The `mastodown` console command is registered in `pyproject.toml` and calls `mastodown.cli:main`.
|
|
16
|
+
- `cli.py` owns argparse setup and orchestration. Both `query` and `download` use the same query arguments; `run_query()` delegates to `query_obs()`, prints its dataframe, and optionally writes CSV. `download` then asks for confirmation unless `--yes` is supplied.
|
|
17
|
+
- `query.py` translates CLI/library filters into `astroquery.mast.Observations` calls for JWST. It fetches observations, gets and filters their products, joins `target_name` back from the observation table, and returns a pandas dataframe with `target_name` as its first column. Target-acquisition filtering uses the JWST mission metadata interface unless `keep_ta=True`.
|
|
18
|
+
- `download.py` consumes that dataframe and requires its product, proposal, target, and data URI columns. It derives `local_path`, compares it with `<download-dir>/manifest.csv`, downloads only required products, and updates the manifest only with successful downloads. Proposal directories are enabled by default; target directories use `target_directory_name()` to produce filesystem-safe names.
|
|
19
|
+
- Sphinx documentation is in `docs/`. `docs/Makefile` runs `generate_api_reference.py` before HTML builds, while `docs/conf.py` regenerates `cli-reference.md` from `cli.py` at Sphinx startup. `docs/cli-reference.md` is generated output; change the parser or generator rather than editing its content manually.
|
|
20
|
+
|
|
21
|
+
## Repository Conventions
|
|
22
|
+
|
|
23
|
+
- Keep the CLI parser, `COMMAND_NAMES`, generated CLI reference, and CLI reference tests aligned whenever commands or options change. Run the freshness check after parser changes.
|
|
24
|
+
- Preserve the shared argument forwarding contract between `query` and `download`: `add_query_arguments()` defines it once, and `run_query()` is the only CLI-to-`query_obs()` bridge.
|
|
25
|
+
- Authentication is intentionally centralized in `authenticate()`: use `MAST_API_TOKEN` when present; only trigger Astroquery's interactive login when `--auth` is set and no environment token exists.
|
|
26
|
+
- Query validation is library-level: date bounds must be supplied together in exact `YYYY-MM-DD` form, end dates are inclusive, and `max_entries` must be positive. Tests mock Astroquery network methods, so new query behavior should remain testable without live MAST access.
|
|
27
|
+
- Treat `manifest.csv` as the download state source of truth. Reconcile missing files already recorded in it, add already-present unrecorded files, and do not record failed downloads. `dry_run=True` must avoid filesystem writes, including the manifest.
|
|
28
|
+
- Tests use `unittest.TestCase` with `unittest.mock` and `pytest` as the runner. Patch dependencies at their use site (for example, `mastodown.query.Observations` or `mastodown.cli.query_obs`) and use temporary directories for download filesystem behavior.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Read the Docs configuration file for Mastodown.
|
|
2
|
+
version: 2
|
|
3
|
+
|
|
4
|
+
build:
|
|
5
|
+
os: ubuntu-24.04
|
|
6
|
+
tools:
|
|
7
|
+
python: "3.13"
|
|
8
|
+
|
|
9
|
+
python:
|
|
10
|
+
install:
|
|
11
|
+
- method: uv
|
|
12
|
+
command: sync
|
|
13
|
+
groups:
|
|
14
|
+
- docs
|
|
15
|
+
|
|
16
|
+
sphinx:
|
|
17
|
+
configuration: docs/conf.py
|
|
18
|
+
fail_on_warning: true
|
mastodown-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thomas Vandal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mastodown-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mastodown
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Tiny Python MAST Client
|
|
5
|
+
Author-email: Thomas Vandal <thomas.vandal@umontreal.ca>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: astroquery
|
|
9
|
+
Requires-Dist: pandas
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# Mastodown
|
|
13
|
+
|
|
14
|
+
Mastodown is a small Python client for querying and downloading data from the
|
|
15
|
+
[MAST](https://mast.stsci.edu/) archive on the command line or from Python.
|
|
16
|
+
|
|
17
|
+
Read the [documentation](https://mastodown.readthedocs.io/) for installation,
|
|
18
|
+
command-line usage, authentication, and the Python API reference.
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python -m pip install git+https://github.com/vandalt/mastodown.git
|
|
24
|
+
mastodown query --programs 01200 02473 --calib-level 1 --product-type SCIENCE --extension fits -o products.csv
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
See the [CLI guide](https://mastodown.readthedocs.io/en/latest/cli.html) for all
|
|
28
|
+
commands and options.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Mastodown
|
|
2
|
+
|
|
3
|
+
Mastodown is a small Python client for querying and downloading data from the
|
|
4
|
+
[MAST](https://mast.stsci.edu/) archive on the command line or from Python.
|
|
5
|
+
|
|
6
|
+
Read the [documentation](https://mastodown.readthedocs.io/) for installation,
|
|
7
|
+
command-line usage, authentication, and the Python API reference.
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m pip install git+https://github.com/vandalt/mastodown.git
|
|
13
|
+
mastodown query --programs 01200 02473 --calib-level 1 --product-type SCIENCE --extension fits -o products.csv
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
See the [CLI guide](https://mastodown.readthedocs.io/en/latest/cli.html) for all
|
|
17
|
+
commands and options.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
SPHINXOPTS ?=
|
|
2
|
+
SPHINXBUILD ?= sphinx-build
|
|
3
|
+
PYTHON = python
|
|
4
|
+
SOURCEDIR = .
|
|
5
|
+
BUILDDIR = _build
|
|
6
|
+
|
|
7
|
+
help:
|
|
8
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
9
|
+
|
|
10
|
+
api:
|
|
11
|
+
@$(PYTHON) generate_api_reference.py
|
|
12
|
+
|
|
13
|
+
html: api
|
|
14
|
+
@$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" -W $(SPHINXOPTS) $(O)
|
|
15
|
+
|
|
16
|
+
.PHONY: help api html Makefile
|
|
17
|
+
|
|
18
|
+
%: Makefile
|
|
19
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" -W $(SPHINXOPTS) $(O)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
mastodown.cli module
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
.. automodule:: mastodown.cli
|
|
5
|
+
:members:
|
|
6
|
+
:exclude-members: ArgumentParser, DataFrame, InvalidQueryError, MastMissions, Namespace, Observations, Path, Series, Time, concat, datetime, environ, read_csv, sub, timedelta
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
:undoc-members:
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
mastodown.download module
|
|
2
|
+
=========================
|
|
3
|
+
|
|
4
|
+
.. automodule:: mastodown.download
|
|
5
|
+
:members:
|
|
6
|
+
:exclude-members: ArgumentParser, DataFrame, InvalidQueryError, MastMissions, Namespace, Observations, Path, Series, Time, concat, datetime, environ, read_csv, sub, timedelta
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
:undoc-members:
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
mastodown.query module
|
|
2
|
+
======================
|
|
3
|
+
|
|
4
|
+
.. automodule:: mastodown.query
|
|
5
|
+
:members:
|
|
6
|
+
:exclude-members: ArgumentParser, DataFrame, InvalidQueryError, MastMissions, Namespace, Observations, Path, Series, Time, concat, datetime, environ, read_csv, sub, timedelta
|
|
7
|
+
:show-inheritance:
|
|
8
|
+
:undoc-members:
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Command line recipes
|
|
2
|
+
|
|
3
|
+
For complete option details, see the {doc}`command reference <cli-reference>`.
|
|
4
|
+
|
|
5
|
+
## Viewing MAST metadata columns
|
|
6
|
+
|
|
7
|
+
List metadata for all available MAST observation columns:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mastodown get-meta
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Querying products
|
|
14
|
+
|
|
15
|
+
Query JWST products and save the resulting table to CSV:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mastodown query --programs 01200 02473 --calib-level 1 --product-type SCIENCE --extension fits -o products.csv
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Filter options accept one or more space-separated values. Use `--keep-ta` to
|
|
22
|
+
retain target-acquisition observations and `--verbose` to print observation
|
|
23
|
+
details. Use `--filters` for MAST instrument filters,
|
|
24
|
+
`--date-range START_DATE END_DATE` for inclusive `YYYY-MM-DD` observation
|
|
25
|
+
dates, and `--max-entries` to limit returned observations.
|
|
26
|
+
|
|
27
|
+
## Downloading products
|
|
28
|
+
|
|
29
|
+
Query products and download them after confirmation:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
mastodown download --programs 01200 02473 --download-dir data --dry-run
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The download command prompts after showing the query result; press Enter to
|
|
36
|
+
continue, enter `n` to cancel, or pass `-y` / `--yes` to skip the prompt. Use
|
|
37
|
+
`--query-output products.csv` to save the query result, and
|
|
38
|
+
`--no-proposal-subdir` to save files directly in the download directory. Use
|
|
39
|
+
`--target-subdir` to place each product under its target name, after the
|
|
40
|
+
optional proposal directory.
|
|
41
|
+
|
|
42
|
+
(proprietary-data-without-an-environment-variable)=
|
|
43
|
+
## Accessing proprietary data without an environment variable
|
|
44
|
+
|
|
45
|
+
As described in the {ref}`installation docs <accessing-proprietary-data>`,
|
|
46
|
+
the simplest way to access proprietary data is by storing your MAST API token in an environment variable.
|
|
47
|
+
|
|
48
|
+
Alternatively, you can pass `--auth` to securely enter a token through Astroquery's prompt:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
mastodown query --programs 01200 --auth
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The environment token takes precedence over `--auth`.
|
|
55
|
+
Do not pass tokens directly on the command line.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Command reference
|
|
2
|
+
|
|
3
|
+
This reference is generated from the CLI's `--help` output. Do not edit it manually.
|
|
4
|
+
|
|
5
|
+
## `mastodown`
|
|
6
|
+
|
|
7
|
+
```console
|
|
8
|
+
$ mastodown --help
|
|
9
|
+
usage: mastodown [-h] {get-meta,query,download} ...
|
|
10
|
+
|
|
11
|
+
Tiny Python MAST client.
|
|
12
|
+
|
|
13
|
+
positional arguments:
|
|
14
|
+
{get-meta,query,download}
|
|
15
|
+
get-meta List metadata for all MAST observation columns. Should
|
|
16
|
+
match the web portal interface.
|
|
17
|
+
query Query the MAST observations portal.
|
|
18
|
+
download Query the MAST observations portal and download the
|
|
19
|
+
matching products.
|
|
20
|
+
|
|
21
|
+
options:
|
|
22
|
+
-h, --help show this help message and exit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## `mastodown get-meta`
|
|
26
|
+
|
|
27
|
+
```console
|
|
28
|
+
$ mastodown get-meta --help
|
|
29
|
+
usage: mastodown get-meta [-h]
|
|
30
|
+
|
|
31
|
+
List metadata for all MAST observation columns. Should match the web portal
|
|
32
|
+
interface.
|
|
33
|
+
|
|
34
|
+
options:
|
|
35
|
+
-h, --help show this help message and exit
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## `mastodown query`
|
|
39
|
+
|
|
40
|
+
```console
|
|
41
|
+
$ mastodown query --help
|
|
42
|
+
usage: mastodown query [-h] [--programs PROGRAMS [PROGRAMS ...]]
|
|
43
|
+
[--calib-level CALIB_LEVEL [CALIB_LEVEL ...]]
|
|
44
|
+
[--product-type PRODUCT_TYPE [PRODUCT_TYPE ...]]
|
|
45
|
+
[--extension EXTENSION [EXTENSION ...]]
|
|
46
|
+
[--filters FILTERS [FILTERS ...]]
|
|
47
|
+
[--date-range START_DATE END_DATE]
|
|
48
|
+
[--max-entries MAX_ENTRIES] [--keep-ta] [--verbose]
|
|
49
|
+
[--auth] [-o QUERY_OUTPUT]
|
|
50
|
+
|
|
51
|
+
Query the MAST observations portal.
|
|
52
|
+
|
|
53
|
+
options:
|
|
54
|
+
-h, --help show this help message and exit
|
|
55
|
+
--programs PROGRAMS [PROGRAMS ...]
|
|
56
|
+
Proposal IDs to query.
|
|
57
|
+
--calib-level CALIB_LEVEL [CALIB_LEVEL ...]
|
|
58
|
+
Calibration levels of products to include.
|
|
59
|
+
--product-type PRODUCT_TYPE [PRODUCT_TYPE ...]
|
|
60
|
+
Product types to include.
|
|
61
|
+
--extension EXTENSION [EXTENSION ...]
|
|
62
|
+
File extensions to include.
|
|
63
|
+
--filters FILTERS [FILTERS ...]
|
|
64
|
+
MAST instrument filters to include.
|
|
65
|
+
--date-range START_DATE END_DATE
|
|
66
|
+
Inclusive observation dates in YYYY-MM-DD format.
|
|
67
|
+
--max-entries MAX_ENTRIES
|
|
68
|
+
Maximum number of observations to return.
|
|
69
|
+
--keep-ta Keep target-acquisition observations.
|
|
70
|
+
--verbose Print matching observations and product summary
|
|
71
|
+
details.
|
|
72
|
+
--auth Prompt securely for a MAST API token when
|
|
73
|
+
MAST_API_TOKEN is not set.
|
|
74
|
+
-o, --output QUERY_OUTPUT
|
|
75
|
+
Write the resulting dataframe to this CSV path.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## `mastodown download`
|
|
79
|
+
|
|
80
|
+
```console
|
|
81
|
+
$ mastodown download --help
|
|
82
|
+
usage: mastodown download [-h] [--programs PROGRAMS [PROGRAMS ...]]
|
|
83
|
+
[--calib-level CALIB_LEVEL [CALIB_LEVEL ...]]
|
|
84
|
+
[--product-type PRODUCT_TYPE [PRODUCT_TYPE ...]]
|
|
85
|
+
[--extension EXTENSION [EXTENSION ...]]
|
|
86
|
+
[--filters FILTERS [FILTERS ...]]
|
|
87
|
+
[--date-range START_DATE END_DATE]
|
|
88
|
+
[--max-entries MAX_ENTRIES] [--keep-ta] [--verbose]
|
|
89
|
+
[--auth] [--query-output QUERY_OUTPUT]
|
|
90
|
+
[--download-dir DOWNLOAD_DIR] [--overwrite]
|
|
91
|
+
[--dry-run] [--no-proposal-subdir] [--target-subdir]
|
|
92
|
+
[-y]
|
|
93
|
+
|
|
94
|
+
Query the MAST observations portal and download the matching products.
|
|
95
|
+
|
|
96
|
+
options:
|
|
97
|
+
-h, --help show this help message and exit
|
|
98
|
+
--programs PROGRAMS [PROGRAMS ...]
|
|
99
|
+
Proposal IDs to query.
|
|
100
|
+
--calib-level CALIB_LEVEL [CALIB_LEVEL ...]
|
|
101
|
+
Calibration levels of products to include.
|
|
102
|
+
--product-type PRODUCT_TYPE [PRODUCT_TYPE ...]
|
|
103
|
+
Product types to include.
|
|
104
|
+
--extension EXTENSION [EXTENSION ...]
|
|
105
|
+
File extensions to include.
|
|
106
|
+
--filters FILTERS [FILTERS ...]
|
|
107
|
+
MAST instrument filters to include.
|
|
108
|
+
--date-range START_DATE END_DATE
|
|
109
|
+
Inclusive observation dates in YYYY-MM-DD format.
|
|
110
|
+
--max-entries MAX_ENTRIES
|
|
111
|
+
Maximum number of observations to return.
|
|
112
|
+
--keep-ta Keep target-acquisition observations.
|
|
113
|
+
--verbose Print matching observations and product summary
|
|
114
|
+
details.
|
|
115
|
+
--auth Prompt securely for a MAST API token when
|
|
116
|
+
MAST_API_TOKEN is not set.
|
|
117
|
+
--query-output QUERY_OUTPUT
|
|
118
|
+
Write the resulting dataframe to this CSV path.
|
|
119
|
+
--download-dir DOWNLOAD_DIR
|
|
120
|
+
Directory in which to save downloaded products.
|
|
121
|
+
--overwrite Download products even when they already exist.
|
|
122
|
+
--dry-run List planned downloads without writing files.
|
|
123
|
+
--no-proposal-subdir Save products directly in the download directory.
|
|
124
|
+
--target-subdir Group downloaded products into target-name
|
|
125
|
+
subdirectories.
|
|
126
|
+
-y, --yes Download without prompting for confirmation.
|
|
127
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Configuration for the Mastodown Sphinx documentation."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
DOCS_DIR = Path(__file__).resolve().parent
|
|
7
|
+
sys.path.insert(0, str(DOCS_DIR))
|
|
8
|
+
sys.path.insert(0, str(DOCS_DIR.parent / "src"))
|
|
9
|
+
|
|
10
|
+
project = "Mastodown"
|
|
11
|
+
copyright = "2026, Thomas Vandal"
|
|
12
|
+
author = "Thomas Vandal"
|
|
13
|
+
|
|
14
|
+
extensions = [
|
|
15
|
+
"myst_parser",
|
|
16
|
+
"sphinx.ext.autodoc",
|
|
17
|
+
"sphinx.ext.viewcode",
|
|
18
|
+
"sphinx_autodoc_typehints",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
source_suffix = {
|
|
22
|
+
".rst": "restructuredtext",
|
|
23
|
+
".md": "markdown",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|
27
|
+
html_theme = "furo"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def generate_cli_reference(_: object) -> None:
|
|
31
|
+
"""Refresh generated CLI help before Sphinx reads source files."""
|
|
32
|
+
from generate_cli_reference import write_reference
|
|
33
|
+
|
|
34
|
+
write_reference()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def setup(app: object) -> None:
|
|
38
|
+
"""Register documentation build hooks."""
|
|
39
|
+
app.connect("builder-inited", generate_cli_reference)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Generate API reference pages from the Mastodown package."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
DOCS_DIR = Path(__file__).resolve().parent
|
|
8
|
+
PROJECT_DIR = DOCS_DIR.parent
|
|
9
|
+
API_DIR = DOCS_DIR / "api"
|
|
10
|
+
PACKAGE_DIR = PROJECT_DIR / "src" / "mastodown"
|
|
11
|
+
INDEX_PATH = API_DIR / "index.rst"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> None:
|
|
15
|
+
"""Generate module pages and an API-reference toctree."""
|
|
16
|
+
API_DIR.mkdir(exist_ok=True)
|
|
17
|
+
|
|
18
|
+
for path in API_DIR.glob("mastodown*.rst"):
|
|
19
|
+
path.unlink()
|
|
20
|
+
|
|
21
|
+
subprocess.run(
|
|
22
|
+
[
|
|
23
|
+
sys.executable,
|
|
24
|
+
"-m",
|
|
25
|
+
"sphinx.ext.apidoc",
|
|
26
|
+
"--separate",
|
|
27
|
+
"--no-toc",
|
|
28
|
+
"--force",
|
|
29
|
+
"-o",
|
|
30
|
+
str(API_DIR),
|
|
31
|
+
str(PACKAGE_DIR),
|
|
32
|
+
],
|
|
33
|
+
check=True,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# The package overview duplicates the flat API index's role and introduces
|
|
37
|
+
# duplicate toctree references for each module.
|
|
38
|
+
(API_DIR / "mastodown.rst").unlink()
|
|
39
|
+
modules = sorted(path.stem for path in API_DIR.glob("mastodown.*.rst"))
|
|
40
|
+
for module in modules:
|
|
41
|
+
exclude_imported_members(API_DIR / f"{module}.rst")
|
|
42
|
+
INDEX_PATH.write_text(
|
|
43
|
+
"API Reference\n"
|
|
44
|
+
"=============\n"
|
|
45
|
+
"\n"
|
|
46
|
+
".. toctree::\n"
|
|
47
|
+
" :maxdepth: 1\n"
|
|
48
|
+
"\n"
|
|
49
|
+
+ "".join(f" {module}\n" for module in modules),
|
|
50
|
+
encoding="utf-8",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def exclude_imported_members(path: Path) -> None:
|
|
55
|
+
"""Keep autodoc focused on Mastodown's public objects."""
|
|
56
|
+
content = path.read_text(encoding="utf-8")
|
|
57
|
+
content = content.replace(
|
|
58
|
+
" :members:\n",
|
|
59
|
+
(
|
|
60
|
+
" :members:\n"
|
|
61
|
+
" :exclude-members: ArgumentParser, DataFrame, InvalidQueryError, "
|
|
62
|
+
"MastMissions, Namespace, Observations, Path, Series, Time, concat, "
|
|
63
|
+
"datetime, environ, read_csv, sub, timedelta\n"
|
|
64
|
+
),
|
|
65
|
+
1,
|
|
66
|
+
)
|
|
67
|
+
path.write_text(content, encoding="utf-8")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
main()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Generate the command-line reference from Mastodown's argument parser."""
|
|
2
|
+
|
|
3
|
+
from argparse import ArgumentParser
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import re
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
DOCS_DIR = Path(__file__).resolve().parent
|
|
9
|
+
PROJECT_DIR = DOCS_DIR.parent
|
|
10
|
+
REFERENCE_PATH = DOCS_DIR / "cli-reference.md"
|
|
11
|
+
ANSI_ESCAPE_PATTERN = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
|
|
12
|
+
|
|
13
|
+
sys.path.insert(0, str(PROJECT_DIR / "src"))
|
|
14
|
+
|
|
15
|
+
from mastodown.cli import COMMAND_NAMES, create_parser
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def format_command_help(parser: ArgumentParser, command: str | None = None) -> str:
|
|
19
|
+
"""Return formatted help for the root parser or one subcommand."""
|
|
20
|
+
if command is None:
|
|
21
|
+
return ANSI_ESCAPE_PATTERN.sub("", parser.format_help()).rstrip()
|
|
22
|
+
|
|
23
|
+
for action in parser._actions:
|
|
24
|
+
choices = getattr(action, "choices", None)
|
|
25
|
+
if choices is not None and command in choices:
|
|
26
|
+
return ANSI_ESCAPE_PATTERN.sub("", choices[command].format_help()).rstrip()
|
|
27
|
+
|
|
28
|
+
msg = f"Command {command!r} is not registered with the argument parser."
|
|
29
|
+
raise ValueError(msg)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def render_reference() -> str:
|
|
33
|
+
"""Render the complete command reference as MyST Markdown."""
|
|
34
|
+
parser = create_parser()
|
|
35
|
+
sections = [
|
|
36
|
+
"# Command reference",
|
|
37
|
+
"",
|
|
38
|
+
"This reference is generated from the CLI's `--help` output. Do not edit it manually.",
|
|
39
|
+
]
|
|
40
|
+
for command in (None, *COMMAND_NAMES):
|
|
41
|
+
invocation = "mastodown" if command is None else f"mastodown {command}"
|
|
42
|
+
sections.extend(
|
|
43
|
+
[
|
|
44
|
+
"",
|
|
45
|
+
f"## `{invocation}`",
|
|
46
|
+
"",
|
|
47
|
+
"```console",
|
|
48
|
+
f"$ {invocation} --help",
|
|
49
|
+
format_command_help(parser, command),
|
|
50
|
+
"```",
|
|
51
|
+
]
|
|
52
|
+
)
|
|
53
|
+
return "\n".join(sections) + "\n"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def write_reference(*, check: bool = False) -> None:
|
|
57
|
+
"""Write the reference, or fail when the committed version is stale."""
|
|
58
|
+
content = render_reference()
|
|
59
|
+
if check:
|
|
60
|
+
if not REFERENCE_PATH.is_file() or REFERENCE_PATH.read_text(
|
|
61
|
+
encoding="utf-8"
|
|
62
|
+
) != content:
|
|
63
|
+
msg = f"{REFERENCE_PATH.relative_to(PROJECT_DIR)} is out of date."
|
|
64
|
+
raise SystemExit(msg)
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
REFERENCE_PATH.write_text(content, encoding="utf-8")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main() -> None:
|
|
71
|
+
"""Generate the reference, accepting a freshness-check mode."""
|
|
72
|
+
write_reference(check="--check" in sys.argv[1:])
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
main()
|