intersphinx-registry 0.2511.7__py2.py3-none-any.whl → 0.2601.5__py2.py3-none-any.whl
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.
- intersphinx_registry/__init__.py +39 -12
- intersphinx_registry/__main__.py +4 -0
- intersphinx_registry/_info.py +4 -4
- intersphinx_registry/cli.py +128 -0
- intersphinx_registry/lookup.py +142 -42
- intersphinx_registry/registry.json +2 -3
- intersphinx_registry/rev_search.py +720 -0
- intersphinx_registry/reverse_lookup.py +247 -0
- intersphinx_registry/utils.py +125 -0
- intersphinx_registry-0.2601.5.dist-info/METADATA +173 -0
- intersphinx_registry-0.2601.5.dist-info/RECORD +15 -0
- intersphinx_registry-0.2601.5.dist-info/entry_points.txt +3 -0
- intersphinx_registry-0.2511.7.dist-info/METADATA +0 -88
- intersphinx_registry-0.2511.7.dist-info/RECORD +0 -9
- {intersphinx_registry-0.2511.7.dist-info → intersphinx_registry-0.2601.5.dist-info}/WHEEL +0 -0
- {intersphinx_registry-0.2511.7.dist-info → intersphinx_registry-0.2601.5.dist-info}/licenses/LICENSE +0 -0
intersphinx_registry/__init__.py
CHANGED
|
@@ -4,28 +4,36 @@ This package provides convenient utilities and data to write a sphinx config fil
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
from pathlib import Path
|
|
8
7
|
import json
|
|
9
|
-
|
|
8
|
+
import warnings
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional, Tuple, cast
|
|
10
11
|
|
|
11
12
|
# See issue 4, we this the best format is Major.YYMM.day,
|
|
12
13
|
# in case of multiple releases a day we can borrow the next day's date.
|
|
13
14
|
# no 0 in front of the day as it is not pep440 compliant.
|
|
14
|
-
version_info = (0,
|
|
15
|
+
version_info = (0, 2601, 5)
|
|
15
16
|
__version__ = ".".join(map(str, version_info))
|
|
16
17
|
|
|
17
18
|
registry_file = Path(__file__).parent / "registry.json"
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
# Mapping of removed aliases to their canonical package names
|
|
21
|
+
_ALIASES = {
|
|
22
|
+
"rtd": "readthedocs",
|
|
23
|
+
"server": "jupyter-server",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _get_all_mappings() -> dict[str, tuple[str, str | None]]:
|
|
20
28
|
return cast(
|
|
21
|
-
|
|
29
|
+
dict[str, Tuple[str, Optional[str]]],
|
|
22
30
|
{k: tuple(v) for (k, v) in json.loads(registry_file.read_bytes()).items()},
|
|
23
31
|
)
|
|
24
32
|
|
|
25
33
|
|
|
26
34
|
def get_intersphinx_mapping(
|
|
27
|
-
*, packages:
|
|
28
|
-
) ->
|
|
35
|
+
*, packages: set[str] = set()
|
|
36
|
+
) -> dict[str, tuple[str, str | None]]:
|
|
29
37
|
"""
|
|
30
38
|
Return values of intersphinx_mapping for sphinx configuration.
|
|
31
39
|
|
|
@@ -37,16 +45,35 @@ def get_intersphinx_mapping(
|
|
|
37
45
|
packages: Set of Str
|
|
38
46
|
Libraries to include.
|
|
39
47
|
|
|
40
|
-
Sphinx will download and load all the `objects.inv` for listed
|
|
48
|
+
Sphinx will download and load all the `objects.inv` for listed
|
|
41
49
|
packages. Getting all mappings is discourage as it will download all
|
|
42
50
|
the `object.inv` which can be a non-negligible amount of data.
|
|
43
51
|
|
|
44
52
|
"""
|
|
45
53
|
if len(packages) == 0:
|
|
46
|
-
raise ValueError(
|
|
54
|
+
raise ValueError(
|
|
55
|
+
'You must explicitly give a list of packages for which to download intersphinx inventories: get_intersphinx_mapping(packages=["IPython", "numpy",...]).'
|
|
56
|
+
)
|
|
47
57
|
|
|
48
58
|
mapping = _get_all_mappings()
|
|
49
|
-
|
|
59
|
+
|
|
60
|
+
# Check for aliases and replace them with canonical names
|
|
61
|
+
resolved_packages = set()
|
|
62
|
+
for pkg in packages:
|
|
63
|
+
if pkg in _ALIASES:
|
|
64
|
+
canonical = _ALIASES[pkg]
|
|
65
|
+
warnings.warn(
|
|
66
|
+
f"Package alias '{pkg}' is deprecated. Use '{canonical}' instead.",
|
|
67
|
+
DeprecationWarning,
|
|
68
|
+
stacklevel=2,
|
|
69
|
+
)
|
|
70
|
+
resolved_packages.add(canonical)
|
|
71
|
+
else:
|
|
72
|
+
resolved_packages.add(pkg)
|
|
73
|
+
|
|
74
|
+
missing = resolved_packages - set(mapping)
|
|
50
75
|
if missing:
|
|
51
|
-
raise ValueError(
|
|
52
|
-
|
|
76
|
+
raise ValueError(
|
|
77
|
+
f"Some libraries in 'packages' not found in registry: {repr(sorted(missing))}"
|
|
78
|
+
)
|
|
79
|
+
return {k: v for k, v in mapping.items() if k in resolved_packages}
|
intersphinx_registry/_info.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Experimental, print info about all (or a subset of), all the known inventories.
|
|
3
3
|
|
|
4
|
-
As this is likely to make _many_ concurrent connections;
|
|
5
|
-
we use
|
|
4
|
+
As this is likely to make _many_ concurrent connections;
|
|
5
|
+
we use aiohttp and sphobjinv which are not listed as dependencies.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
@@ -66,7 +66,7 @@ for key, base_url, data in results:
|
|
|
66
66
|
flattened.append((key, base_url, inv.project, inv.version, inv.count))
|
|
67
67
|
|
|
68
68
|
if not flattened:
|
|
69
|
-
sys.exit("Could not reach any
|
|
69
|
+
sys.exit("Could not reach any packages")
|
|
70
70
|
width = [len(x) for x in flattened[0][:-1]]
|
|
71
71
|
|
|
72
72
|
for item in flattened:
|
|
@@ -76,5 +76,5 @@ for item in flattened:
|
|
|
76
76
|
for key, url, proj, version, count in flattened:
|
|
77
77
|
w_key, w_url, w_proj, w_version = width
|
|
78
78
|
print(
|
|
79
|
-
f"{key:<{w_key}} {proj!r:<{w_proj+2}} {version:<{w_version}} {count:<5} {url:<{w_url}}"
|
|
79
|
+
f"{key:<{w_key}} {proj!r:<{w_proj + 2}} {version:<{w_version}} {count:<5} {url:<{w_url}}"
|
|
80
80
|
)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from intersphinx_registry import __version__
|
|
5
|
+
from intersphinx_registry.lookup import clear_cache, lookup_packages, print_info
|
|
6
|
+
from intersphinx_registry.reverse_lookup import reverse_lookup
|
|
7
|
+
from intersphinx_registry.rev_search import rev_search
|
|
8
|
+
from intersphinx_registry.utils import _are_dependencies_available
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def lookup_command(args):
|
|
12
|
+
if not _are_dependencies_available():
|
|
13
|
+
sys.exit(1)
|
|
14
|
+
|
|
15
|
+
if not args.packages:
|
|
16
|
+
print("Usage: intersphinx-registry lookup <package>[,package] [search_term]\n")
|
|
17
|
+
print("Examples:")
|
|
18
|
+
print(" intersphinx-registry lookup numpy,scipy array")
|
|
19
|
+
print(" intersphinx-registry lookup ipython formatters.html")
|
|
20
|
+
sys.exit(0)
|
|
21
|
+
|
|
22
|
+
lookup_packages(args.packages, args.search_term)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
parser = argparse.ArgumentParser(
|
|
27
|
+
prog="intersphinx-registry",
|
|
28
|
+
description="Default intersphinx mapping for the Python ecosystem",
|
|
29
|
+
epilog="For more information, see: https://github.com/Quansight-labs/intersphinx_registry",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"-v",
|
|
34
|
+
"--version",
|
|
35
|
+
action="version",
|
|
36
|
+
version=f"intersphinx-registry {__version__}",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
subparsers = parser.add_subparsers(
|
|
40
|
+
title="subcommands",
|
|
41
|
+
description="available subcommands",
|
|
42
|
+
dest="subcommand",
|
|
43
|
+
help="subcommand help",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Lookup subcommand
|
|
47
|
+
lookup_parser = subparsers.add_parser(
|
|
48
|
+
"lookup",
|
|
49
|
+
help="Search and lookup intersphinx targets/webpages",
|
|
50
|
+
description="Search intersphinx inventories for documentation targets",
|
|
51
|
+
)
|
|
52
|
+
lookup_parser.add_argument(
|
|
53
|
+
"packages",
|
|
54
|
+
nargs="?",
|
|
55
|
+
default=None,
|
|
56
|
+
help="Comma-separated list of package names (e.g., numpy,scipy)",
|
|
57
|
+
)
|
|
58
|
+
lookup_parser.add_argument(
|
|
59
|
+
"search_term",
|
|
60
|
+
nargs="?",
|
|
61
|
+
default=None,
|
|
62
|
+
help="Optional search term to filter results",
|
|
63
|
+
)
|
|
64
|
+
lookup_parser.set_defaults(func=lookup_command)
|
|
65
|
+
|
|
66
|
+
reverse_lookup_parser = subparsers.add_parser(
|
|
67
|
+
"reverse-lookup",
|
|
68
|
+
help="Find which packages documentation URLs belong to",
|
|
69
|
+
description="Given URLs, find which packages they come from",
|
|
70
|
+
epilog="Examples:\n"
|
|
71
|
+
" intersphinx-registry reverse-lookup https://numpy.org/doc/stable/reference/arrays.html\n"
|
|
72
|
+
" intersphinx-registry reverse-lookup https://docs.python.org/3/ https://numpy.org/doc/stable/",
|
|
73
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
74
|
+
)
|
|
75
|
+
reverse_lookup_parser.add_argument(
|
|
76
|
+
"urls",
|
|
77
|
+
nargs="*",
|
|
78
|
+
help="URLs to look up (space-separated)",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def _reverse_lookup_wrapper(args):
|
|
82
|
+
if not args.urls:
|
|
83
|
+
reverse_lookup_parser.print_help()
|
|
84
|
+
sys.exit(0)
|
|
85
|
+
reverse_lookup(args.urls)
|
|
86
|
+
|
|
87
|
+
reverse_lookup_parser.set_defaults(func=_reverse_lookup_wrapper)
|
|
88
|
+
|
|
89
|
+
rev_search_parser = subparsers.add_parser(
|
|
90
|
+
"rev-search",
|
|
91
|
+
help="Search .rst files for URLs that can be replaced with Sphinx references",
|
|
92
|
+
description="Scan directory for .rst files and find URLs that can be replaced",
|
|
93
|
+
epilog="Examples:\n"
|
|
94
|
+
" intersphinx-registry rev-search docs/\n"
|
|
95
|
+
" intersphinx-registry rev-search .",
|
|
96
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
97
|
+
)
|
|
98
|
+
rev_search_parser.add_argument(
|
|
99
|
+
"directory",
|
|
100
|
+
help="Directory to search for .rst files",
|
|
101
|
+
)
|
|
102
|
+
rev_search_parser.set_defaults(func=lambda args: rev_search(args.directory))
|
|
103
|
+
|
|
104
|
+
clear_cache_parser = subparsers.add_parser(
|
|
105
|
+
"clear-cache",
|
|
106
|
+
help="Clear the intersphinx inventory cache",
|
|
107
|
+
description="Clear the cached intersphinx inventory files",
|
|
108
|
+
)
|
|
109
|
+
clear_cache_parser.set_defaults(func=lambda args: clear_cache())
|
|
110
|
+
|
|
111
|
+
info_parser = subparsers.add_parser(
|
|
112
|
+
"info",
|
|
113
|
+
help="Display information about the intersphinx-registry installation",
|
|
114
|
+
description="Show version, cache location, registry file location, and package count",
|
|
115
|
+
)
|
|
116
|
+
info_parser.set_defaults(func=lambda args: print_info())
|
|
117
|
+
|
|
118
|
+
args = parser.parse_args()
|
|
119
|
+
|
|
120
|
+
if args.subcommand is None:
|
|
121
|
+
parser.print_help()
|
|
122
|
+
sys.exit(0)
|
|
123
|
+
|
|
124
|
+
args.func(args)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
main()
|
intersphinx_registry/lookup.py
CHANGED
|
@@ -1,67 +1,142 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import shutil
|
|
1
3
|
import sys
|
|
2
|
-
|
|
3
|
-
from
|
|
4
|
-
from . import __version__
|
|
5
|
-
from urllib.parse import urljoin
|
|
6
|
-
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
from pathlib import Path
|
|
7
6
|
from typing import Optional
|
|
7
|
+
from urllib.parse import urljoin
|
|
8
8
|
|
|
9
|
+
import requests
|
|
9
10
|
from sphinx.util.inventory import InventoryFile
|
|
10
|
-
from io import BytesIO
|
|
11
11
|
|
|
12
|
-
import
|
|
12
|
+
from . import __version__, get_intersphinx_mapping
|
|
13
|
+
from .utils import (
|
|
14
|
+
_are_dependencies_available,
|
|
15
|
+
_compress_user_path,
|
|
16
|
+
_get_cache_dir,
|
|
17
|
+
_install_cache,
|
|
18
|
+
)
|
|
13
19
|
|
|
14
|
-
if len(sys.argv) not in [2, 3]:
|
|
15
|
-
sys.exit(
|
|
16
|
-
"""Usage: python -m intersphinx_registry.lookup <package>[,package] [search_term]
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
def clear_cache() -> None:
|
|
22
|
+
"""Clear the intersphinx inventory cache for the current version."""
|
|
23
|
+
if not _are_dependencies_available():
|
|
24
|
+
return
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
$ python -m intersphinx_registry.lookup ipython formatters.html
|
|
26
|
+
cache_dir = _get_cache_dir()
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
if cache_dir.exists():
|
|
29
|
+
for item in cache_dir.iterdir():
|
|
30
|
+
try:
|
|
31
|
+
if item.is_file():
|
|
32
|
+
item.unlink()
|
|
33
|
+
elif item.is_dir():
|
|
34
|
+
shutil.rmtree(item)
|
|
35
|
+
except Exception as e:
|
|
36
|
+
print(f"Warning: Could not remove {item}: {e}")
|
|
37
|
+
|
|
38
|
+
print("Cache cleared successfully")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_info() -> dict[str, str]:
|
|
42
|
+
"""
|
|
43
|
+
Get information about the intersphinx-registry installation.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
dict[str, str]
|
|
48
|
+
Dictionary containing version and cache location
|
|
49
|
+
"""
|
|
50
|
+
info = {
|
|
51
|
+
"version": __version__,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
cache_dir = _get_cache_dir()
|
|
56
|
+
info["cache_location"] = str(cache_dir)
|
|
57
|
+
except Exception:
|
|
58
|
+
info["cache_location"] = "N/A (dependencies not installed)"
|
|
59
|
+
|
|
60
|
+
return info
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def print_info() -> None:
|
|
64
|
+
"""Print information about the intersphinx-registry installation."""
|
|
65
|
+
info = get_info()
|
|
25
66
|
|
|
67
|
+
cache_location = _compress_user_path(info["cache_location"])
|
|
26
68
|
|
|
27
|
-
|
|
28
|
-
print(
|
|
69
|
+
print("Intersphinx Registry Information")
|
|
70
|
+
print("=" * 50)
|
|
71
|
+
print(f"Version: {info['version']}")
|
|
72
|
+
print(f"Cache location: {cache_location}")
|
|
29
73
|
|
|
30
|
-
|
|
74
|
+
try:
|
|
75
|
+
registry_file_path = Path(__file__).parent / "registry.json"
|
|
76
|
+
registry = json.loads(registry_file_path.read_bytes())
|
|
77
|
+
print(f"Packages in registry: {len(registry)}")
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"Packages in registry: Error reading registry ({e})")
|
|
31
80
|
|
|
32
|
-
search_term: Optional[str]
|
|
33
|
-
if len(sys.argv) == 3:
|
|
34
|
-
search_term = sys.argv[2]
|
|
35
|
-
else:
|
|
36
|
-
search_term = None
|
|
37
81
|
|
|
38
|
-
|
|
82
|
+
def lookup_packages(packages_str: str, search_term: Optional[str] = None) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Look up intersphinx targets for specified packages.
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
packages_str : str
|
|
89
|
+
Comma-separated list of package names
|
|
90
|
+
search_term : str, optional
|
|
91
|
+
Search term to filter results
|
|
92
|
+
"""
|
|
93
|
+
if not _are_dependencies_available():
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
packages = set(packages_str.split(","))
|
|
97
|
+
|
|
98
|
+
_install_cache()
|
|
99
|
+
|
|
39
100
|
urls = [
|
|
40
101
|
(u[0], (u[1] if u[1] else "objects.inv"))
|
|
41
102
|
for u in get_intersphinx_mapping(packages=packages).values()
|
|
42
103
|
]
|
|
43
104
|
|
|
44
|
-
flattened = []
|
|
105
|
+
flattened: list[tuple[str, str, str, str, str, str]] = []
|
|
45
106
|
for base_url, obj in urls:
|
|
46
|
-
|
|
47
107
|
final_url = urljoin(base_url, obj)
|
|
48
108
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
109
|
+
try:
|
|
110
|
+
resp = requests.get(final_url, timeout=30)
|
|
111
|
+
resp.raise_for_status()
|
|
112
|
+
inv = InventoryFile.load(BytesIO(resp.content), base_url, urljoin)
|
|
113
|
+
except requests.RequestException as e:
|
|
114
|
+
print(f"Warning: Failed to fetch {final_url}: {e}", file=sys.stderr)
|
|
115
|
+
continue
|
|
116
|
+
except Exception as e:
|
|
117
|
+
print(
|
|
118
|
+
f"Warning: Failed to load inventory from {final_url}: {e}",
|
|
119
|
+
file=sys.stderr,
|
|
120
|
+
)
|
|
121
|
+
continue
|
|
52
122
|
|
|
53
123
|
for key, v in inv.items():
|
|
54
124
|
inv_entries = sorted(v.items())
|
|
55
|
-
for entry,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
125
|
+
for entry, item in inv_entries:
|
|
126
|
+
flattened.append(
|
|
127
|
+
(
|
|
128
|
+
key,
|
|
129
|
+
entry,
|
|
130
|
+
item.project_name,
|
|
131
|
+
item.project_version,
|
|
132
|
+
item.display_name,
|
|
133
|
+
item.uri,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
filtered: list[tuple[str, str, str, str, str, str]] = []
|
|
138
|
+
for item_tuple in flattened:
|
|
139
|
+
key, entry, proj, version, display_name, url_path = item_tuple
|
|
65
140
|
if (
|
|
66
141
|
(search_term is None)
|
|
67
142
|
or (search_term in entry)
|
|
@@ -69,15 +144,40 @@ def main():
|
|
|
69
144
|
or (search_term in url_path)
|
|
70
145
|
):
|
|
71
146
|
filtered.append((key, entry, proj, version, display_name, url_path))
|
|
72
|
-
width = [max(w, len(x)) for w, x in zip(width, item)]
|
|
73
147
|
|
|
148
|
+
if not filtered:
|
|
149
|
+
return
|
|
150
|
+
|
|
151
|
+
width = [0] * 6
|
|
152
|
+
for item_tuple in filtered:
|
|
153
|
+
for i, x in enumerate(item_tuple):
|
|
154
|
+
width[i] = max(width[i], len(str(x)))
|
|
74
155
|
|
|
75
156
|
for key, entry, proj, version, display_name, url_path in filtered:
|
|
76
157
|
w_key, w_entry, w_proj, w_version, w_di, w_url = width
|
|
77
158
|
print(
|
|
78
|
-
f"{key:<{w_key}} {entry:<{w_entry}} {proj:<{w_proj}}
|
|
159
|
+
f"{key:<{w_key}} {entry:<{w_entry}} {proj:<{w_proj}} "
|
|
160
|
+
f"{version:<{w_version}} {display_name!r:<{w_di + 2}} {url_path}"
|
|
79
161
|
)
|
|
80
162
|
|
|
81
163
|
|
|
82
164
|
if __name__ == "__main__":
|
|
83
|
-
|
|
165
|
+
if len(sys.argv) not in [2, 3]:
|
|
166
|
+
sys.exit(
|
|
167
|
+
"""Usage: python -m intersphinx_registry.lookup <package>[,package] [search_term]
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
|
|
171
|
+
$ python -m intersphinx_registry.lookup numpy,scipy array
|
|
172
|
+
$ python -m intersphinx_registry.lookup ipython formatters.html
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
packages_str = sys.argv[1]
|
|
178
|
+
search_term = sys.argv[2] if len(sys.argv) == 3 else None
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
lookup_packages(packages_str, search_term)
|
|
182
|
+
except Exception as e:
|
|
183
|
+
sys.exit(f"ERROR: {e}")
|
|
@@ -119,6 +119,7 @@
|
|
|
119
119
|
"poliastro": ["https://docs.poliastro.space/en/stable/", null],
|
|
120
120
|
"pooch": ["https://www.fatiando.org/pooch/latest/", null],
|
|
121
121
|
"prompt_toolkit": ["https://python-prompt-toolkit.readthedocs.io/en/stable/", null],
|
|
122
|
+
"py-free-threading": ["https://py-free-threading.github.io/", null],
|
|
122
123
|
"py": ["https://pylib.readthedocs.io/en/latest/", null],
|
|
123
124
|
"pyarrow": ["https://arrow.apache.org/docs/", null],
|
|
124
125
|
"pybaselines": ["https://pybaselines.readthedocs.io/en/stable/", null],
|
|
@@ -152,14 +153,12 @@
|
|
|
152
153
|
"rpy2": ["https://rpy2.github.io/doc/latest/html/", null],
|
|
153
154
|
"rsciio": ["https://hyperspy.org/rosettasciio/", null],
|
|
154
155
|
"rst-to-myst": ["https://rst-to-myst.readthedocs.io/en/stable/", null],
|
|
155
|
-
"rtd": ["https://docs.readthedocs.io/en/stable/", null],
|
|
156
156
|
"rtd-dev": ["https://dev.readthedocs.io/en/latest/", null],
|
|
157
157
|
"scanpy": ["https://scanpy.readthedocs.io/en/stable/", null],
|
|
158
|
-
"scipy": ["https://scipy.
|
|
158
|
+
"scipy": ["https://docs.scipy.org/doc/scipy/", null],
|
|
159
159
|
"scipy-lecture-notes": ["https://scipy-lectures.org/", null],
|
|
160
160
|
"scriptconfig": ["https://scriptconfig.readthedocs.io/en/latest/", null],
|
|
161
161
|
"seaborn": ["https://seaborn.pydata.org/", null],
|
|
162
|
-
"server": ["https://jupyter-server.readthedocs.io/en/stable/", null],
|
|
163
162
|
"setuptools": ["https://setuptools.pypa.io/en/stable/", null],
|
|
164
163
|
"six": ["https://six.readthedocs.io/", null],
|
|
165
164
|
"skimage": ["https://scikit-image.org/docs/stable/", null],
|