napistu 0.2.5.dev7__py3-none-any.whl → 0.3.1.dev1__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.
- napistu/__init__.py +1 -3
- napistu/__main__.py +126 -96
- napistu/constants.py +35 -41
- napistu/context/__init__.py +10 -0
- napistu/context/discretize.py +462 -0
- napistu/context/filtering.py +387 -0
- napistu/gcs/__init__.py +1 -1
- napistu/identifiers.py +74 -15
- napistu/indices.py +68 -0
- napistu/ingestion/__init__.py +1 -1
- napistu/ingestion/bigg.py +47 -62
- napistu/ingestion/constants.py +18 -133
- napistu/ingestion/gtex.py +113 -0
- napistu/ingestion/hpa.py +147 -0
- napistu/ingestion/sbml.py +0 -97
- napistu/ingestion/string.py +2 -2
- napistu/matching/__init__.py +10 -0
- napistu/matching/constants.py +18 -0
- napistu/matching/interactions.py +518 -0
- napistu/matching/mount.py +529 -0
- napistu/matching/species.py +510 -0
- napistu/mcp/__init__.py +7 -4
- napistu/mcp/__main__.py +128 -72
- napistu/mcp/client.py +16 -25
- napistu/mcp/codebase.py +201 -145
- napistu/mcp/component_base.py +170 -0
- napistu/mcp/config.py +223 -0
- napistu/mcp/constants.py +45 -2
- napistu/mcp/documentation.py +253 -136
- napistu/mcp/documentation_utils.py +13 -48
- napistu/mcp/execution.py +372 -305
- napistu/mcp/health.py +47 -65
- napistu/mcp/profiles.py +10 -6
- napistu/mcp/server.py +161 -80
- napistu/mcp/tutorials.py +139 -87
- napistu/modify/__init__.py +1 -1
- napistu/modify/gaps.py +1 -1
- napistu/network/__init__.py +1 -1
- napistu/network/constants.py +101 -34
- napistu/network/data_handling.py +388 -0
- napistu/network/ig_utils.py +351 -0
- napistu/network/napistu_graph_core.py +354 -0
- napistu/network/neighborhoods.py +40 -40
- napistu/network/net_create.py +373 -309
- napistu/network/net_propagation.py +47 -19
- napistu/network/{net_utils.py → ng_utils.py} +124 -272
- napistu/network/paths.py +67 -51
- napistu/network/precompute.py +11 -11
- napistu/ontologies/__init__.py +10 -0
- napistu/ontologies/constants.py +129 -0
- napistu/ontologies/dogma.py +243 -0
- napistu/ontologies/genodexito.py +649 -0
- napistu/ontologies/mygene.py +369 -0
- napistu/ontologies/renaming.py +198 -0
- napistu/rpy2/__init__.py +229 -86
- napistu/rpy2/callr.py +47 -77
- napistu/rpy2/constants.py +24 -23
- napistu/rpy2/rids.py +61 -648
- napistu/sbml_dfs_core.py +587 -222
- napistu/scverse/__init__.py +15 -0
- napistu/scverse/constants.py +28 -0
- napistu/scverse/loading.py +727 -0
- napistu/utils.py +118 -10
- {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/METADATA +8 -3
- napistu-0.3.1.dev1.dist-info/RECORD +133 -0
- tests/conftest.py +22 -0
- tests/test_context_discretize.py +56 -0
- tests/test_context_filtering.py +267 -0
- tests/test_identifiers.py +100 -0
- tests/test_indices.py +65 -0
- tests/{test_edgelist.py → test_ingestion_napistu_edgelist.py} +2 -2
- tests/test_matching_interactions.py +108 -0
- tests/test_matching_mount.py +305 -0
- tests/test_matching_species.py +394 -0
- tests/test_mcp_config.py +193 -0
- tests/test_mcp_documentation_utils.py +12 -3
- tests/test_mcp_server.py +156 -19
- tests/test_network_data_handling.py +397 -0
- tests/test_network_ig_utils.py +23 -0
- tests/test_network_neighborhoods.py +19 -0
- tests/test_network_net_create.py +459 -0
- tests/test_network_ng_utils.py +30 -0
- tests/test_network_paths.py +56 -0
- tests/{test_precomputed_distances.py → test_network_precompute.py} +8 -6
- tests/test_ontologies_genodexito.py +58 -0
- tests/test_ontologies_mygene.py +39 -0
- tests/test_ontologies_renaming.py +110 -0
- tests/test_rpy2_callr.py +79 -0
- tests/test_rpy2_init.py +151 -0
- tests/test_sbml.py +0 -31
- tests/test_sbml_dfs_core.py +134 -10
- tests/test_scverse_loading.py +778 -0
- tests/test_set_coverage.py +2 -2
- tests/test_utils.py +121 -1
- napistu/mechanism_matching.py +0 -1353
- napistu/rpy2/netcontextr.py +0 -467
- napistu-0.2.5.dev7.dist-info/RECORD +0 -98
- tests/test_igraph.py +0 -367
- tests/test_mechanism_matching.py +0 -784
- tests/test_net_utils.py +0 -149
- tests/test_netcontextr.py +0 -105
- tests/test_rpy2.py +0 -61
- /napistu/ingestion/{cpr_edgelist.py → napistu_edgelist.py} +0 -0
- {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/WHEEL +0 -0
- {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/entry_points.txt +0 -0
- {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/licenses/LICENSE +0 -0
- {napistu-0.2.5.dev7.dist-info → napistu-0.3.1.dev1.dist-info}/top_level.txt +0 -0
- /tests/{test_obo.py → test_ingestion_obo.py} +0 -0
napistu/mcp/documentation.py
CHANGED
@@ -2,165 +2,282 @@
|
|
2
2
|
Documentation components for the Napistu MCP server.
|
3
3
|
"""
|
4
4
|
|
5
|
+
from typing import Dict, Any
|
6
|
+
import logging
|
7
|
+
|
5
8
|
from fastmcp import FastMCP
|
6
9
|
|
10
|
+
from napistu.mcp.component_base import ComponentState, MCPComponent
|
7
11
|
from napistu.mcp import documentation_utils
|
8
12
|
from napistu.mcp import utils as mcp_utils
|
9
|
-
from napistu.mcp.constants import DOCUMENTATION, READMES, REPOS_WITH_ISSUES
|
10
|
-
|
11
|
-
# Global cache for documentation content
|
12
|
-
_docs_cache = {
|
13
|
-
DOCUMENTATION.README: {},
|
14
|
-
DOCUMENTATION.WIKI: {},
|
15
|
-
DOCUMENTATION.ISSUES: {},
|
16
|
-
DOCUMENTATION.PRS: {},
|
17
|
-
DOCUMENTATION.PACKAGEDOWN: {},
|
18
|
-
}
|
13
|
+
from napistu.mcp.constants import DOCUMENTATION, READMES, REPOS_WITH_ISSUES, WIKI_PAGES
|
19
14
|
|
15
|
+
logger = logging.getLogger(__name__)
|
20
16
|
|
21
|
-
async def initialize_components() -> bool:
|
22
|
-
"""
|
23
|
-
Initialize documentation components.
|
24
|
-
Loads documentation content and should be called before the server starts handling requests.
|
25
|
-
|
26
|
-
Returns
|
27
|
-
-------
|
28
|
-
bool
|
29
|
-
True if initialization is successful.
|
30
|
-
"""
|
31
|
-
global _docs_cache
|
32
|
-
# Load documentation from the READMES dict
|
33
|
-
for name, url in READMES.items():
|
34
|
-
_docs_cache[DOCUMENTATION.README][name] = (
|
35
|
-
await documentation_utils.load_readme_content(url)
|
36
|
-
)
|
37
|
-
# Load issue and PR summaries with the GitHub API
|
38
|
-
for repo in REPOS_WITH_ISSUES:
|
39
|
-
_docs_cache[DOCUMENTATION.ISSUES][repo] = await documentation_utils.list_issues(
|
40
|
-
repo
|
41
|
-
)
|
42
|
-
_docs_cache[DOCUMENTATION.PRS][repo] = (
|
43
|
-
await documentation_utils.list_pull_requests(repo)
|
44
|
-
)
|
45
|
-
return True
|
46
17
|
|
18
|
+
class DocumentationState(ComponentState):
|
19
|
+
"""State management for documentation component."""
|
47
20
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
21
|
+
def __init__(self):
|
22
|
+
super().__init__()
|
23
|
+
self.docs_cache: Dict[str, Dict[str, Any]] = {
|
24
|
+
DOCUMENTATION.README: {},
|
25
|
+
DOCUMENTATION.WIKI: {},
|
26
|
+
DOCUMENTATION.ISSUES: {},
|
27
|
+
DOCUMENTATION.PRS: {},
|
28
|
+
DOCUMENTATION.PACKAGEDOWN: {},
|
29
|
+
}
|
51
30
|
|
52
|
-
|
53
|
-
|
54
|
-
|
31
|
+
def is_healthy(self) -> bool:
|
32
|
+
"""Component is healthy if it has loaded any documentation."""
|
33
|
+
return any(bool(section) for section in self.docs_cache.values())
|
55
34
|
|
56
|
-
|
57
|
-
|
58
|
-
async def get_documentation_summary():
|
59
|
-
"""
|
60
|
-
Get a summary of all available documentation.
|
61
|
-
"""
|
35
|
+
def get_health_details(self) -> Dict[str, Any]:
|
36
|
+
"""Provide documentation-specific health details."""
|
62
37
|
return {
|
63
|
-
"
|
64
|
-
"
|
65
|
-
"
|
66
|
-
"
|
67
|
-
"
|
38
|
+
"readme_count": len(self.docs_cache[DOCUMENTATION.README]),
|
39
|
+
"wiki_pages": len(self.docs_cache[DOCUMENTATION.WIKI]),
|
40
|
+
"issues_repos": len(self.docs_cache[DOCUMENTATION.ISSUES]),
|
41
|
+
"prs_repos": len(self.docs_cache[DOCUMENTATION.PRS]),
|
42
|
+
"total_sections": sum(len(section) for section in self.docs_cache.values()),
|
68
43
|
}
|
69
44
|
|
70
|
-
@mcp.resource("napistu://documentation/readme/{file_name}")
|
71
|
-
async def get_readme_content(file_name: str):
|
72
|
-
"""
|
73
|
-
Get the content of a specific README file.
|
74
45
|
|
75
|
-
|
76
|
-
|
77
|
-
"""
|
78
|
-
if file_name not in _docs_cache[DOCUMENTATION.README]:
|
79
|
-
return {"error": f"README file {file_name} not found"}
|
46
|
+
class DocumentationComponent(MCPComponent):
|
47
|
+
"""MCP component for documentation management and search."""
|
80
48
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
}
|
49
|
+
def _create_state(self) -> DocumentationState:
|
50
|
+
"""Create documentation-specific state."""
|
51
|
+
return DocumentationState()
|
85
52
|
|
86
|
-
|
87
|
-
async def get_issues(repo: str):
|
88
|
-
"""
|
89
|
-
Get the list of issues for a given repository.
|
53
|
+
async def initialize(self) -> bool:
|
90
54
|
"""
|
91
|
-
|
55
|
+
Initialize documentation component by loading all documentation sources.
|
92
56
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
57
|
+
Returns
|
58
|
+
-------
|
59
|
+
bool
|
60
|
+
True if at least some documentation was loaded successfully
|
97
61
|
"""
|
98
|
-
|
62
|
+
success_count = 0
|
63
|
+
total_operations = 0
|
99
64
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
65
|
+
# Load README files
|
66
|
+
logger.info("Loading README files...")
|
67
|
+
for name, url in READMES.items():
|
68
|
+
total_operations += 1
|
69
|
+
try:
|
70
|
+
content = await documentation_utils.load_readme_content(url)
|
71
|
+
self.state.docs_cache[DOCUMENTATION.README][name] = content
|
72
|
+
success_count += 1
|
73
|
+
logger.debug(f"Loaded README: {name}")
|
74
|
+
except Exception as e:
|
75
|
+
logger.warning(f"Failed to load README {name}: {e}")
|
76
|
+
|
77
|
+
# Load wiki pages
|
78
|
+
logger.info("Loading wiki pages...")
|
79
|
+
for page in WIKI_PAGES:
|
80
|
+
total_operations += 1
|
81
|
+
try:
|
82
|
+
content = await documentation_utils.fetch_wiki_page(page)
|
83
|
+
self.state.docs_cache[DOCUMENTATION.WIKI][page] = content
|
84
|
+
success_count += 1
|
85
|
+
logger.debug(f"Loaded wiki page: {page}")
|
86
|
+
except Exception as e:
|
87
|
+
logger.warning(f"Failed to load wiki page {page}: {e}")
|
88
|
+
|
89
|
+
# Load issues and PRs
|
90
|
+
logger.info("Loading issues and pull requests...")
|
91
|
+
for repo in REPOS_WITH_ISSUES:
|
92
|
+
total_operations += 2 # Issues and PRs
|
93
|
+
try:
|
94
|
+
issues = await documentation_utils.list_issues(repo)
|
95
|
+
self.state.docs_cache[DOCUMENTATION.ISSUES][repo] = issues
|
96
|
+
success_count += 1
|
97
|
+
logger.debug(f"Loaded issues for repo: {repo}")
|
98
|
+
except Exception as e:
|
99
|
+
logger.warning(f"Failed to load issues for {repo}: {e}")
|
100
|
+
|
101
|
+
try:
|
102
|
+
prs = await documentation_utils.list_pull_requests(repo)
|
103
|
+
self.state.docs_cache[DOCUMENTATION.PRS][repo] = prs
|
104
|
+
success_count += 1
|
105
|
+
logger.debug(f"Loaded PRs for repo: {repo}")
|
106
|
+
except Exception as e:
|
107
|
+
logger.warning(f"Failed to load PRs for {repo}: {e}")
|
108
|
+
|
109
|
+
logger.info(
|
110
|
+
f"Documentation loading complete: {success_count}/{total_operations} operations successful"
|
113
111
|
)
|
114
|
-
if cached:
|
115
|
-
return cached
|
116
|
-
# Fallback to live fetch
|
117
|
-
return await documentation_utils.get_issue(repo, number)
|
118
112
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
113
|
+
# Consider successful if at least some documentation loaded
|
114
|
+
return success_count > 0
|
115
|
+
|
116
|
+
def register(self, mcp: FastMCP) -> None:
|
123
117
|
"""
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
),
|
131
|
-
None,
|
132
|
-
)
|
133
|
-
if cached:
|
134
|
-
return cached
|
135
|
-
# Fallback to live fetch
|
136
|
-
return await documentation_utils.get_issue(repo, number)
|
137
|
-
|
138
|
-
# Register tools
|
139
|
-
@mcp.tool()
|
140
|
-
async def search_documentation(query: str):
|
118
|
+
Register documentation resources and tools with the MCP server.
|
119
|
+
|
120
|
+
Parameters
|
121
|
+
----------
|
122
|
+
mcp : FastMCP
|
123
|
+
FastMCP server instance
|
141
124
|
"""
|
142
|
-
Search all documentation for a specific query.
|
143
125
|
|
144
|
-
|
145
|
-
|
126
|
+
# Register resources
|
127
|
+
@mcp.resource("napistu://documentation/summary")
|
128
|
+
async def get_documentation_summary():
|
129
|
+
"""Get a summary of all available documentation."""
|
130
|
+
return {
|
131
|
+
"readme_files": list(
|
132
|
+
self.state.docs_cache[DOCUMENTATION.README].keys()
|
133
|
+
),
|
134
|
+
"issues": list(self.state.docs_cache[DOCUMENTATION.ISSUES].keys()),
|
135
|
+
"prs": list(self.state.docs_cache[DOCUMENTATION.PRS].keys()),
|
136
|
+
"wiki_pages": list(self.state.docs_cache[DOCUMENTATION.WIKI].keys()),
|
137
|
+
"packagedown_sections": list(
|
138
|
+
self.state.docs_cache[DOCUMENTATION.PACKAGEDOWN].keys()
|
139
|
+
),
|
140
|
+
}
|
146
141
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
142
|
+
@mcp.resource("napistu://documentation/readme/{file_name}")
|
143
|
+
async def get_readme_content(file_name: str):
|
144
|
+
"""Get the content of a specific README file."""
|
145
|
+
if file_name not in self.state.docs_cache[DOCUMENTATION.README]:
|
146
|
+
return {"error": f"README file {file_name} not found"}
|
147
|
+
|
148
|
+
return {
|
149
|
+
"content": self.state.docs_cache[DOCUMENTATION.README][file_name],
|
150
|
+
"format": "markdown",
|
151
|
+
}
|
152
|
+
|
153
|
+
@mcp.resource("napistu://documentation/issues/{repo}")
|
154
|
+
async def get_issues(repo: str):
|
155
|
+
"""Get the list of issues for a given repository."""
|
156
|
+
return self.state.docs_cache[DOCUMENTATION.ISSUES].get(repo, [])
|
157
|
+
|
158
|
+
@mcp.resource("napistu://documentation/prs/{repo}")
|
159
|
+
async def get_prs(repo: str):
|
160
|
+
"""Get the list of pull requests for a given repository."""
|
161
|
+
return self.state.docs_cache[DOCUMENTATION.PRS].get(repo, [])
|
162
|
+
|
163
|
+
@mcp.resource("napistu://documentation/issue/{repo}/{number}")
|
164
|
+
async def get_issue_resource(repo: str, number: int):
|
165
|
+
"""Get a single issue by number for a given repository."""
|
166
|
+
# Try cache first
|
167
|
+
cached = next(
|
168
|
+
(
|
169
|
+
i
|
170
|
+
for i in self.state.docs_cache[DOCUMENTATION.ISSUES].get(repo, [])
|
171
|
+
if i["number"] == number
|
172
|
+
),
|
173
|
+
None,
|
174
|
+
)
|
175
|
+
if cached:
|
176
|
+
return cached
|
177
|
+
# Fallback to live fetch
|
178
|
+
return await documentation_utils.get_issue(repo, number)
|
179
|
+
|
180
|
+
@mcp.resource("napistu://documentation/pr/{repo}/{number}")
|
181
|
+
async def get_pr_resource(repo: str, number: int):
|
182
|
+
"""Get a single pull request by number for a given repository."""
|
183
|
+
# Try cache first
|
184
|
+
cached = next(
|
185
|
+
(
|
186
|
+
pr
|
187
|
+
for pr in self.state.docs_cache[DOCUMENTATION.PRS].get(repo, [])
|
188
|
+
if pr["number"] == number
|
189
|
+
),
|
190
|
+
None,
|
191
|
+
)
|
192
|
+
if cached:
|
193
|
+
return cached
|
194
|
+
# Fallback to live fetch
|
195
|
+
return await documentation_utils.get_issue(repo, number)
|
196
|
+
|
197
|
+
# Register tools
|
198
|
+
@mcp.tool()
|
199
|
+
async def search_documentation(query: str):
|
200
|
+
"""
|
201
|
+
Search all documentation for a specific query.
|
202
|
+
|
203
|
+
Args:
|
204
|
+
query: Search term
|
205
|
+
|
206
|
+
Returns:
|
207
|
+
Dictionary with search results organized by documentation type
|
208
|
+
"""
|
209
|
+
results = {
|
210
|
+
DOCUMENTATION.README: [],
|
211
|
+
DOCUMENTATION.WIKI: [],
|
212
|
+
DOCUMENTATION.ISSUES: [],
|
213
|
+
DOCUMENTATION.PRS: [],
|
214
|
+
DOCUMENTATION.PACKAGEDOWN: [],
|
215
|
+
}
|
216
|
+
|
217
|
+
# Search README files
|
218
|
+
for readme_name, content in self.state.docs_cache[
|
219
|
+
DOCUMENTATION.README
|
220
|
+
].items():
|
221
|
+
if query.lower() in content.lower():
|
222
|
+
results[DOCUMENTATION.README].append(
|
223
|
+
{
|
224
|
+
"name": readme_name,
|
225
|
+
"snippet": mcp_utils.get_snippet(content, query),
|
226
|
+
}
|
227
|
+
)
|
228
|
+
|
229
|
+
# Search wiki pages
|
230
|
+
for page_name, content in self.state.docs_cache[DOCUMENTATION.WIKI].items():
|
231
|
+
if query.lower() in content.lower():
|
232
|
+
results[DOCUMENTATION.WIKI].append(
|
233
|
+
{
|
234
|
+
"name": page_name,
|
235
|
+
"snippet": mcp_utils.get_snippet(content, query),
|
236
|
+
}
|
237
|
+
)
|
238
|
+
|
239
|
+
# Search issues
|
240
|
+
for repo, issues in self.state.docs_cache[DOCUMENTATION.ISSUES].items():
|
241
|
+
for issue in issues:
|
242
|
+
issue_text = f"{issue.get('title', '')} {issue.get('body', '')}"
|
243
|
+
if query.lower() in issue_text.lower():
|
244
|
+
results[DOCUMENTATION.ISSUES].append(
|
245
|
+
{
|
246
|
+
"name": f"{repo}#{issue.get('number')}",
|
247
|
+
"title": issue.get("title"),
|
248
|
+
"url": issue.get("url"),
|
249
|
+
"snippet": mcp_utils.get_snippet(issue_text, query),
|
250
|
+
}
|
251
|
+
)
|
252
|
+
|
253
|
+
# Search PRs
|
254
|
+
for repo, prs in self.state.docs_cache[DOCUMENTATION.PRS].items():
|
255
|
+
for pr in prs:
|
256
|
+
pr_text = f"{pr.get('title', '')} {pr.get('body', '')}"
|
257
|
+
if query.lower() in pr_text.lower():
|
258
|
+
results[DOCUMENTATION.PRS].append(
|
259
|
+
{
|
260
|
+
"name": f"{repo}#{pr.get('number')}",
|
261
|
+
"title": pr.get("title"),
|
262
|
+
"url": pr.get("url"),
|
263
|
+
"snippet": mcp_utils.get_snippet(pr_text, query),
|
264
|
+
}
|
265
|
+
)
|
266
|
+
|
267
|
+
return results
|
268
|
+
|
269
|
+
|
270
|
+
# Module-level component instance
|
271
|
+
_component = DocumentationComponent()
|
272
|
+
|
273
|
+
|
274
|
+
def get_component() -> DocumentationComponent:
|
275
|
+
"""
|
276
|
+
Get the documentation component instance.
|
277
|
+
|
278
|
+
Returns
|
279
|
+
-------
|
280
|
+
DocumentationComponent
|
281
|
+
The documentation component instance
|
282
|
+
"""
|
283
|
+
return _component
|
@@ -2,7 +2,6 @@
|
|
2
2
|
Utilities for loading and processing documentation.
|
3
3
|
"""
|
4
4
|
|
5
|
-
import base64
|
6
5
|
import httpx
|
7
6
|
import os
|
8
7
|
from napistu.constants import PACKAGE_DEFS
|
@@ -25,69 +24,35 @@ async def load_readme_content(readme_url: str) -> str:
|
|
25
24
|
)
|
26
25
|
|
27
26
|
|
28
|
-
async def list_wiki_pages(
|
29
|
-
repo: str,
|
30
|
-
owner: str = PACKAGE_DEFS.GITHUB_OWNER,
|
31
|
-
github_api: str = DEFAULT_GITHUB_API,
|
32
|
-
) -> list:
|
33
|
-
"""
|
34
|
-
List all Markdown (.md) page names in a GitHub wiki using the GitHub API.
|
35
|
-
|
36
|
-
Parameters
|
37
|
-
----------
|
38
|
-
repo : str, optional
|
39
|
-
The repository name.
|
40
|
-
owner : str, optional
|
41
|
-
The GitHub username or organization (default is 'napistu').
|
42
|
-
github_api : str, optional
|
43
|
-
The GitHub API base URL (default is 'https://api.github.com').
|
44
|
-
|
45
|
-
Returns
|
46
|
-
-------
|
47
|
-
list of str
|
48
|
-
List of page names (e.g., ['Home.md', 'Some-Page.md'])
|
49
|
-
"""
|
50
|
-
wiki_repo = f"{repo}.wiki"
|
51
|
-
url = f"{github_api}/repos/{owner}/{wiki_repo}/contents/"
|
52
|
-
async with httpx.AsyncClient(headers=_get_github_headers()) as client:
|
53
|
-
resp = await client.get(url)
|
54
|
-
resp.raise_for_status()
|
55
|
-
return [item["name"] for item in resp.json() if item["name"].endswith(".md")]
|
56
|
-
|
57
|
-
|
58
27
|
async def fetch_wiki_page(
|
59
28
|
page_name: str,
|
60
|
-
repo: str,
|
29
|
+
repo: str = PACKAGE_DEFS.GITHUB_PROJECT_REPO,
|
61
30
|
owner: str = PACKAGE_DEFS.GITHUB_OWNER,
|
62
|
-
github_api: str = DEFAULT_GITHUB_API,
|
63
31
|
) -> str:
|
64
32
|
"""
|
65
|
-
Fetch
|
33
|
+
Fetch wiki page content using raw GitHub URLs.
|
66
34
|
|
67
35
|
Parameters
|
68
36
|
----------
|
69
37
|
page_name : str
|
70
|
-
The name of the page
|
71
|
-
repo : str
|
72
|
-
The repository name
|
73
|
-
owner : str
|
74
|
-
The GitHub username or organization
|
75
|
-
github_api : str, optional
|
76
|
-
The GitHub API base URL (default is 'https://api.github.com').
|
38
|
+
The name of the page (without .md extension for wiki pages)
|
39
|
+
repo : str
|
40
|
+
The repository name
|
41
|
+
owner : str
|
42
|
+
The GitHub username or organization
|
77
43
|
|
78
44
|
Returns
|
79
45
|
-------
|
80
46
|
str
|
81
|
-
The Markdown content
|
47
|
+
The raw Markdown content
|
82
48
|
"""
|
83
|
-
|
84
|
-
url = f"
|
85
|
-
|
49
|
+
# Use raw.githubusercontent.com for wiki pages
|
50
|
+
url = f"https://raw.githubusercontent.com/wiki/{owner}/{repo}/{page_name}.md"
|
51
|
+
|
52
|
+
async with httpx.AsyncClient() as client:
|
86
53
|
resp = await client.get(url)
|
87
54
|
resp.raise_for_status()
|
88
|
-
|
89
|
-
content = base64.b64decode(data["content"]).decode("utf-8")
|
90
|
-
return content
|
55
|
+
return resp.text
|
91
56
|
|
92
57
|
|
93
58
|
async def list_issues(
|