gitcode-api 1.2.18__tar.gz → 1.2.19__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.
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/PKG-INFO +2 -2
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/README.md +1 -1
- gitcode_api-1.2.19/gitcode_api/constants.py +25 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/resources/_shared.py +9 -12
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/resources/collaboration.py +9 -2
- gitcode_api-1.2.19/gitcode_api/version.txt +1 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api.egg-info/PKG-INFO +2 -2
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/pyproject.toml +1 -1
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_collaboration_templates.py +90 -1
- gitcode_api-1.2.18/gitcode_api/constants.py +0 -8
- gitcode_api-1.2.18/gitcode_api/version.txt +0 -1
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/LICENSE +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/__init__.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/__main__.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/_base_client.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/_base_resource.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/_cli_banner.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/_client.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/_exceptions.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/_models.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/cli.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/llm/__init__.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/llm/_tool.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/llm/jiuwen.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/llm/mcp.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/llm/openai.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/py.typed +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/resources/__init__.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/resources/account.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/resources/misc.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/resources/repositories.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/run_mcp.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api/utils.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api.egg-info/SOURCES.txt +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api.egg-info/dependency_links.txt +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api.egg-info/entry_points.txt +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api.egg-info/requires.txt +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/gitcode_api.egg-info/top_level.txt +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/setup.cfg +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_base_client.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_build_manifest.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_cli.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_client.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_llm_tools.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_models.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_resources_account.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_resources_collaboration.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_resources_misc.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_resources_repositories.py +0 -0
- {gitcode_api-1.2.18 → gitcode_api-1.2.19}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitcode-api
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.19
|
|
4
4
|
Summary: Easy to use Python SDK for the GitCode REST API. Providing builtin CLI tool, and optional LLM integration (MCP, OpenAI tool, and openJiuwen tool) for agents. Community-maintained.
|
|
5
5
|
Author-email: Hugo Huang <hugo@hugohuang.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -37,7 +37,7 @@ Dynamic: license-file
|
|
|
37
37
|
|
|
38
38
|
# GitCode-API
|
|
39
39
|
|
|
40
|
-
[](https://pypi.org/project/gitcode-api) [](https://pepy.tech/projects/gitcode-api) [](https://www.codefactor.io/repository/github/trenza1ore/gitcode-api)
|
|
41
41
|
[](https://cursor.com/en/install-mcp?name=GitCode%20API&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJnaXRjb2RlLWFwaVttY3BdIiwiZ2l0Y29kZS1hcGkiLCJzZXJ2ZSJdLCJlbnYiOnsiR0lUQ09ERV9BQ0NFU1NfVE9LRU4iOiIke2lucHV0OmdpdGNvZGVfYWNjZXNzX3Rva2VufSJ9LCJpbnB1dHMiOlt7ImlkIjoiZ2l0Y29kZV9hY2Nlc3NfdG9rZW4iLCJ0eXBlIjoicHJvbXB0U3RyaW5nIiwiZGVzY3JpcHRpb24iOiJFbnRlciBHSVRDT0RFX0FDQ0VTU19UT0tFTiIsInBhc3N3b3JkIjp0cnVlfV19) [](https://vscode.dev/redirect/mcp/install?name=GitCode%20API&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22gitcode-api%5Bmcp%5D%22%2C%22gitcode-api%22%2C%22serve%22%5D%2C%22env%22%3A%7B%22GITCODE_ACCESS_TOKEN%22%3A%22%24%7Binput%3Agitcode_access_token%7D%22%7D%2C%22inputs%22%3A%5B%7B%22id%22%3A%22gitcode_access_token%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Enter%20GITCODE_ACCESS_TOKEN%22%2C%22password%22%3Atrue%7D%5D%7D)
|
|
42
42
|
[](https://github.com/Trenza1ore/GitCode-API) [](https://gitcode.com/SushiNinja/GitCode-API)
|
|
43
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GitCode-API
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/gitcode-api) [](https://pepy.tech/projects/gitcode-api) [](https://www.codefactor.io/repository/github/trenza1ore/gitcode-api)
|
|
4
4
|
[](https://cursor.com/en/install-mcp?name=GitCode%20API&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJnaXRjb2RlLWFwaVttY3BdIiwiZ2l0Y29kZS1hcGkiLCJzZXJ2ZSJdLCJlbnYiOnsiR0lUQ09ERV9BQ0NFU1NfVE9LRU4iOiIke2lucHV0OmdpdGNvZGVfYWNjZXNzX3Rva2VufSJ9LCJpbnB1dHMiOlt7ImlkIjoiZ2l0Y29kZV9hY2Nlc3NfdG9rZW4iLCJ0eXBlIjoicHJvbXB0U3RyaW5nIiwiZGVzY3JpcHRpb24iOiJFbnRlciBHSVRDT0RFX0FDQ0VTU19UT0tFTiIsInBhc3N3b3JkIjp0cnVlfV19) [](https://vscode.dev/redirect/mcp/install?name=GitCode%20API&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22gitcode-api%5Bmcp%5D%22%2C%22gitcode-api%22%2C%22serve%22%5D%2C%22env%22%3A%7B%22GITCODE_ACCESS_TOKEN%22%3A%22%24%7Binput%3Agitcode_access_token%7D%22%7D%2C%22inputs%22%3A%5B%7B%22id%22%3A%22gitcode_access_token%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Enter%20GITCODE_ACCESS_TOKEN%22%2C%22password%22%3Atrue%7D%5D%7D)
|
|
5
5
|
[](https://github.com/Trenza1ore/GitCode-API) [](https://gitcode.com/SushiNinja/GitCode-API)
|
|
6
6
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Shared constant values for the GitCode SDK."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
DEFAULT_BASE_URL = "https://api.gitcode.com/api/v5"
|
|
6
|
+
DEFAULT_TIMEOUT = 30.0
|
|
7
|
+
DEFAULT_TOKEN_ENV = "GITCODE_ACCESS_TOKEN"
|
|
8
|
+
DEFAULT_CA_ENV = "GITCODE_CA_BUNDLE"
|
|
9
|
+
GITCODE_ISSUE_TEMPLATE_PATH_RE: re.Pattern[str] = re.compile(
|
|
10
|
+
r"\.git(code|hub)/ISSUE_TEMPLATE.*\.(md|markdown|ya?ml)$", re.IGNORECASE
|
|
11
|
+
)
|
|
12
|
+
GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE: re.Pattern[str] = re.compile(
|
|
13
|
+
r"\.git(code|hub)/PULL_REQUEST_TEMPLATE.*\.(md|markdown|ya?ml)$", re.IGNORECASE
|
|
14
|
+
)
|
|
15
|
+
GITCODE_TEMPLATE_REPO = ".gitcode"
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"DEFAULT_BASE_URL",
|
|
19
|
+
"DEFAULT_TIMEOUT",
|
|
20
|
+
"DEFAULT_TOKEN_ENV",
|
|
21
|
+
"DEFAULT_CA_ENV",
|
|
22
|
+
"GITCODE_ISSUE_TEMPLATE_PATH_RE",
|
|
23
|
+
"GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE",
|
|
24
|
+
"GITCODE_TEMPLATE_REPO",
|
|
25
|
+
]
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
"""Shared resource base classes for the GitCode SDK."""
|
|
2
2
|
|
|
3
|
-
import re
|
|
4
3
|
from typing import Any, Dict, List, Optional, Pattern, Tuple, Union
|
|
5
4
|
|
|
6
5
|
from .._base_client import AsyncAPIClient, SyncAPIClient
|
|
7
6
|
from .._base_resource import BaseResource
|
|
8
7
|
from .._exceptions import GitCodeHTTPStatusError
|
|
9
8
|
from .._models import APIObject, ModelT, as_model, as_model_list
|
|
10
|
-
|
|
11
|
-
GITCODE_ISSUE_TEMPLATE_PATH_RE: Pattern[str] = re.compile(
|
|
12
|
-
r"\.gitcode/ISSUE_TEMPLATE.*\.(md|markdown|ya?ml)$", re.IGNORECASE
|
|
13
|
-
)
|
|
14
|
-
GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE: Pattern[str] = re.compile(
|
|
15
|
-
r"\.gitcode/PULL_REQUEST_TEMPLATE.*\.(md|markdown|ya?ml)$", re.IGNORECASE
|
|
16
|
-
)
|
|
9
|
+
from ..constants import GITCODE_TEMPLATE_REPO
|
|
17
10
|
|
|
18
11
|
|
|
19
12
|
def _parse_parent_owner_repo(repo_obj: Any) -> Optional[Tuple[str, str]]:
|
|
@@ -50,7 +43,7 @@ def _resolution_sources_sync(client: SyncAPIClient, owner: str, repo: str) -> Li
|
|
|
50
43
|
sources.append(pair)
|
|
51
44
|
|
|
52
45
|
add((owner, repo))
|
|
53
|
-
add((owner,
|
|
46
|
+
add((owner, GITCODE_TEMPLATE_REPO))
|
|
54
47
|
|
|
55
48
|
max_candidates = 64
|
|
56
49
|
index = 0
|
|
@@ -68,7 +61,7 @@ def _resolution_sources_sync(client: SyncAPIClient, owner: str, repo: str) -> Li
|
|
|
68
61
|
continue
|
|
69
62
|
po, pr = parsed
|
|
70
63
|
add((po, pr))
|
|
71
|
-
add((po,
|
|
64
|
+
add((po, GITCODE_TEMPLATE_REPO))
|
|
72
65
|
|
|
73
66
|
return sources
|
|
74
67
|
|
|
@@ -86,7 +79,7 @@ async def _resolution_sources_async(client: AsyncAPIClient, owner: str, repo: st
|
|
|
86
79
|
sources.append(pair)
|
|
87
80
|
|
|
88
81
|
add((owner, repo))
|
|
89
|
-
add((owner,
|
|
82
|
+
add((owner, GITCODE_TEMPLATE_REPO))
|
|
90
83
|
|
|
91
84
|
max_candidates = 64
|
|
92
85
|
index = 0
|
|
@@ -104,7 +97,7 @@ async def _resolution_sources_async(client: AsyncAPIClient, owner: str, repo: st
|
|
|
104
97
|
continue
|
|
105
98
|
po, pr = parsed
|
|
106
99
|
add((po, pr))
|
|
107
|
-
add((po,
|
|
100
|
+
add((po, GITCODE_TEMPLATE_REPO))
|
|
108
101
|
|
|
109
102
|
return sources
|
|
110
103
|
|
|
@@ -210,6 +203,8 @@ def list_gitcode_template_rows_sync(
|
|
|
210
203
|
acc: List[Tuple[str, str, str, str]] = []
|
|
211
204
|
try:
|
|
212
205
|
_walk_dot_gitcode_contents_sync(client, so, sr, ".gitcode", acc)
|
|
206
|
+
if sr != GITCODE_TEMPLATE_REPO:
|
|
207
|
+
_walk_dot_gitcode_contents_sync(client, so, sr, ".github", acc)
|
|
213
208
|
except GitCodeHTTPStatusError:
|
|
214
209
|
continue
|
|
215
210
|
rows = [(t_o, t_r, p, s) for t_o, t_r, p, s in acc if path_pattern.match(p)]
|
|
@@ -228,6 +223,8 @@ async def list_gitcode_template_rows_async(
|
|
|
228
223
|
acc: List[Tuple[str, str, str, str]] = []
|
|
229
224
|
try:
|
|
230
225
|
await _walk_dot_gitcode_contents_async(client, so, sr, ".gitcode", acc)
|
|
226
|
+
if sr != GITCODE_TEMPLATE_REPO:
|
|
227
|
+
await _walk_dot_gitcode_contents_async(client, so, sr, ".github", acc)
|
|
231
228
|
except GitCodeHTTPStatusError:
|
|
232
229
|
continue
|
|
233
230
|
rows = [(t_o, t_r, p, s) for t_o, t_r, p, s in acc if path_pattern.match(p)]
|
|
@@ -25,9 +25,8 @@ from .._models import (
|
|
|
25
25
|
UserSummary,
|
|
26
26
|
as_model,
|
|
27
27
|
)
|
|
28
|
+
from ..constants import GITCODE_ISSUE_TEMPLATE_PATH_RE, GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE
|
|
28
29
|
from ._shared import (
|
|
29
|
-
GITCODE_ISSUE_TEMPLATE_PATH_RE,
|
|
30
|
-
GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE,
|
|
31
30
|
AsyncResource,
|
|
32
31
|
SyncResource,
|
|
33
32
|
get_gitcode_template_body_async,
|
|
@@ -420,6 +419,8 @@ class IssuesResource(SyncResource):
|
|
|
420
419
|
are appended, deduplicated, and visited in order). The first source with matching
|
|
421
420
|
templates wins.
|
|
422
421
|
|
|
422
|
+
Version 1.2.19: Now also supporting GitHub-mirrored repos with a ``.github/`` folder.
|
|
423
|
+
|
|
423
424
|
:param owner: Repository owner path. Uses the client default when omitted.
|
|
424
425
|
:param repo: Repository name. Uses the client default when omitted.
|
|
425
426
|
:returns: Template metadata entries (paths and SHAs); empty when none match.
|
|
@@ -1067,6 +1068,8 @@ class PullsResource(SyncResource):
|
|
|
1067
1068
|
are appended, deduplicated, and visited in order). The first source with matching
|
|
1068
1069
|
templates wins.
|
|
1069
1070
|
|
|
1071
|
+
Version 1.2.19: Now also supporting GitHub-mirrored repos with a ``.github/`` folder.
|
|
1072
|
+
|
|
1070
1073
|
:param owner: Repository owner path. Uses the client default when omitted.
|
|
1071
1074
|
:param repo: Repository path. Uses the client default when omitted.
|
|
1072
1075
|
:returns: Template metadata entries (paths and SHAs); empty when none match.
|
|
@@ -1734,6 +1737,8 @@ class AsyncIssuesResource(AsyncResource):
|
|
|
1734
1737
|
are appended, deduplicated, and visited in order). The first source with matching
|
|
1735
1738
|
templates wins.
|
|
1736
1739
|
|
|
1740
|
+
Version 1.2.19: Now also supporting GitHub-mirrored repos with a ``.github/`` folder.
|
|
1741
|
+
|
|
1737
1742
|
:param owner: Repository owner path. Uses the client default when omitted.
|
|
1738
1743
|
:param repo: Repository name. Uses the client default when omitted.
|
|
1739
1744
|
:returns: Template metadata entries (paths and SHAs); empty when none match.
|
|
@@ -2328,6 +2333,8 @@ class AsyncPullsResource(AsyncResource):
|
|
|
2328
2333
|
are appended, deduplicated, and visited in order). The first source with matching
|
|
2329
2334
|
templates wins.
|
|
2330
2335
|
|
|
2336
|
+
Version 1.2.19: Now also supporting GitHub-mirrored repos with a ``.github/`` folder.
|
|
2337
|
+
|
|
2331
2338
|
:param owner: Repository owner path. Uses the client default when omitted.
|
|
2332
2339
|
:param repo: Repository path. Uses the client default when omitted.
|
|
2333
2340
|
:returns: Template metadata entries (paths and SHAs); empty when none match.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.2.19
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitcode-api
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.19
|
|
4
4
|
Summary: Easy to use Python SDK for the GitCode REST API. Providing builtin CLI tool, and optional LLM integration (MCP, OpenAI tool, and openJiuwen tool) for agents. Community-maintained.
|
|
5
5
|
Author-email: Hugo Huang <hugo@hugohuang.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -37,7 +37,7 @@ Dynamic: license-file
|
|
|
37
37
|
|
|
38
38
|
# GitCode-API
|
|
39
39
|
|
|
40
|
-
[](https://pypi.org/project/gitcode-api) [](https://pepy.tech/projects/gitcode-api) [](https://www.codefactor.io/repository/github/trenza1ore/gitcode-api)
|
|
41
41
|
[](https://cursor.com/en/install-mcp?name=GitCode%20API&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJnaXRjb2RlLWFwaVttY3BdIiwiZ2l0Y29kZS1hcGkiLCJzZXJ2ZSJdLCJlbnYiOnsiR0lUQ09ERV9BQ0NFU1NfVE9LRU4iOiIke2lucHV0OmdpdGNvZGVfYWNjZXNzX3Rva2VufSJ9LCJpbnB1dHMiOlt7ImlkIjoiZ2l0Y29kZV9hY2Nlc3NfdG9rZW4iLCJ0eXBlIjoicHJvbXB0U3RyaW5nIiwiZGVzY3JpcHRpb24iOiJFbnRlciBHSVRDT0RFX0FDQ0VTU19UT0tFTiIsInBhc3N3b3JkIjp0cnVlfV19) [](https://vscode.dev/redirect/mcp/install?name=GitCode%20API&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22gitcode-api%5Bmcp%5D%22%2C%22gitcode-api%22%2C%22serve%22%5D%2C%22env%22%3A%7B%22GITCODE_ACCESS_TOKEN%22%3A%22%24%7Binput%3Agitcode_access_token%7D%22%7D%2C%22inputs%22%3A%5B%7B%22id%22%3A%22gitcode_access_token%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22Enter%20GITCODE_ACCESS_TOKEN%22%2C%22password%22%3Atrue%7D%5D%7D)
|
|
42
42
|
[](https://github.com/Trenza1ore/GitCode-API) [](https://gitcode.com/SushiNinja/GitCode-API)
|
|
43
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "gitcode-api"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.19"
|
|
4
4
|
description = "Easy to use Python SDK for the GitCode REST API. Providing builtin CLI tool, and optional LLM integration (MCP, OpenAI tool, and openJiuwen tool) for agents. Community-maintained."
|
|
5
5
|
keywords = [
|
|
6
6
|
"gitcode", "git", "devops", "api", "sdk", "python", "httpx", "client",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Tests for issue/PR ``.gitcode`` template resolution helpers."""
|
|
1
|
+
"""Tests for issue/PR ``.gitcode`` and ``.github`` template resolution helpers."""
|
|
2
2
|
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
@@ -6,6 +6,10 @@ import httpx
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
8
|
from gitcode_api._exceptions import GitCodeHTTPStatusError
|
|
9
|
+
from gitcode_api.constants import (
|
|
10
|
+
GITCODE_ISSUE_TEMPLATE_PATH_RE,
|
|
11
|
+
GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE,
|
|
12
|
+
)
|
|
9
13
|
|
|
10
14
|
# ``_resolution_sources_*`` probes ``GET /repos/{owner}/{repo}`` for every candidate; stub these.
|
|
11
15
|
_REPO_METADATA_NONFORK_PATHS = frozenset(
|
|
@@ -29,12 +33,22 @@ def _repo_metadata_nonfork_stub(request: httpx.Request, path: str) -> Optional[h
|
|
|
29
33
|
return None
|
|
30
34
|
|
|
31
35
|
|
|
36
|
+
def _empty_github_contents_stub(request: httpx.Request, path: str) -> Optional[httpx.Response]:
|
|
37
|
+
"""Stub ``GET .../contents/.github`` from mirrored-repo template walks."""
|
|
38
|
+
if request.method == "GET" and path.endswith("/contents/.github"):
|
|
39
|
+
return httpx.Response(404, json={"message": "missing"})
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
32
43
|
def test_list_templates_fallback_to_dot_gitcode_repo(sync_client_factory):
|
|
33
44
|
def handler(request: httpx.Request) -> httpx.Response:
|
|
34
45
|
p = request.url.path
|
|
35
46
|
stub = _repo_metadata_nonfork_stub(request, p)
|
|
36
47
|
if stub is not None:
|
|
37
48
|
return stub
|
|
49
|
+
gh = _empty_github_contents_stub(request, p)
|
|
50
|
+
if gh is not None:
|
|
51
|
+
return gh
|
|
38
52
|
if p == "/api/v5/repos/acme/proj" and request.method == "GET":
|
|
39
53
|
return httpx.Response(200, json={"fork": False, "id": 1})
|
|
40
54
|
if p == "/api/v5/repos/acme/proj/contents/.gitcode":
|
|
@@ -68,6 +82,9 @@ def test_list_templates_fork_parent_source(sync_client_factory):
|
|
|
68
82
|
stub = _repo_metadata_nonfork_stub(request, p)
|
|
69
83
|
if stub is not None:
|
|
70
84
|
return stub
|
|
85
|
+
gh = _empty_github_contents_stub(request, p)
|
|
86
|
+
if gh is not None:
|
|
87
|
+
return gh
|
|
71
88
|
if p == "/api/v5/repos/acme/proj" and request.method == "GET":
|
|
72
89
|
return httpx.Response(
|
|
73
90
|
200,
|
|
@@ -111,6 +128,9 @@ def test_list_templates_fork_parent_dot_gitcode_repo(sync_client_factory):
|
|
|
111
128
|
stub = _repo_metadata_nonfork_stub(request, p)
|
|
112
129
|
if stub is not None:
|
|
113
130
|
return stub
|
|
131
|
+
gh = _empty_github_contents_stub(request, p)
|
|
132
|
+
if gh is not None:
|
|
133
|
+
return gh
|
|
114
134
|
if p == "/api/v5/repos/acme/proj" and request.method == "GET":
|
|
115
135
|
return httpx.Response(
|
|
116
136
|
200,
|
|
@@ -153,6 +173,9 @@ def test_list_templates_includes_yaml_issue_forms(sync_client_factory):
|
|
|
153
173
|
stub = _repo_metadata_nonfork_stub(request, p)
|
|
154
174
|
if stub is not None:
|
|
155
175
|
return stub
|
|
176
|
+
gh = _empty_github_contents_stub(request, p)
|
|
177
|
+
if gh is not None:
|
|
178
|
+
return gh
|
|
156
179
|
if p == "/api/v5/repos/acme/proj" and request.method == "GET":
|
|
157
180
|
return httpx.Response(200, json={"fork": False})
|
|
158
181
|
if p == "/api/v5/repos/acme/proj/contents/.gitcode":
|
|
@@ -224,6 +247,9 @@ def test_pulls_list_and_get_template(sync_client_factory):
|
|
|
224
247
|
stub = _repo_metadata_nonfork_stub(request, p)
|
|
225
248
|
if stub is not None:
|
|
226
249
|
return stub
|
|
250
|
+
gh = _empty_github_contents_stub(request, p)
|
|
251
|
+
if gh is not None:
|
|
252
|
+
return gh
|
|
227
253
|
if p == "/api/v5/repos/o/r" and request.method == "GET" and "contents" not in p and "raw" not in p:
|
|
228
254
|
return httpx.Response(200, json={"fork": False})
|
|
229
255
|
if p == "/api/v5/repos/o/r/contents/.gitcode":
|
|
@@ -257,6 +283,9 @@ async def test_async_issues_list_templates(async_client_factory):
|
|
|
257
283
|
stub = _repo_metadata_nonfork_stub(request, p)
|
|
258
284
|
if stub is not None:
|
|
259
285
|
return stub
|
|
286
|
+
gh = _empty_github_contents_stub(request, p)
|
|
287
|
+
if gh is not None:
|
|
288
|
+
return gh
|
|
260
289
|
if p == "/api/v5/repos/acme/proj" and request.method == "GET":
|
|
261
290
|
return httpx.Response(200, json={"fork": False})
|
|
262
291
|
if p == "/api/v5/repos/acme/proj/contents/.gitcode":
|
|
@@ -280,3 +309,63 @@ async def test_async_issues_list_templates(async_client_factory):
|
|
|
280
309
|
await http.aclose()
|
|
281
310
|
assert len(items) == 1
|
|
282
311
|
assert items[0].sha == "asyncsha"
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def test_template_path_patterns_accept_github_paths():
|
|
315
|
+
assert GITCODE_ISSUE_TEMPLATE_PATH_RE.match(".github/ISSUE_TEMPLATE/bug.md")
|
|
316
|
+
assert GITCODE_ISSUE_TEMPLATE_PATH_RE.match(".gitcode/ISSUE_TEMPLATE_bug.yml")
|
|
317
|
+
assert not GITCODE_ISSUE_TEMPLATE_PATH_RE.match(".github/README.md")
|
|
318
|
+
assert GITCODE_PULL_REQUEST_TEMPLATE_PATH_RE.match(".github/PULL_REQUEST_TEMPLATE.md")
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def test_list_templates_from_dot_github(sync_client_factory):
|
|
322
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
323
|
+
p = request.url.path
|
|
324
|
+
stub = _repo_metadata_nonfork_stub(request, p)
|
|
325
|
+
if stub is not None:
|
|
326
|
+
return stub
|
|
327
|
+
if p == "/api/v5/repos/acme/proj" and request.method == "GET":
|
|
328
|
+
return httpx.Response(200, json={"fork": False})
|
|
329
|
+
if p == "/api/v5/repos/acme/proj/contents/.gitcode":
|
|
330
|
+
return httpx.Response(404, json={"message": "missing"})
|
|
331
|
+
if p == "/api/v5/repos/acme/proj/contents/.github":
|
|
332
|
+
return httpx.Response(
|
|
333
|
+
200,
|
|
334
|
+
json=[
|
|
335
|
+
{
|
|
336
|
+
"type": "file",
|
|
337
|
+
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
|
|
338
|
+
"sha": "ghsha",
|
|
339
|
+
}
|
|
340
|
+
],
|
|
341
|
+
)
|
|
342
|
+
if p == "/api/v5/repos/acme/.gitcode/contents/.gitcode":
|
|
343
|
+
return httpx.Response(404, json={"message": "missing"})
|
|
344
|
+
raise AssertionError(f"unexpected {request.method} {p}")
|
|
345
|
+
|
|
346
|
+
client, _ = sync_client_factory(handler, owner="acme", repo="proj")
|
|
347
|
+
items = client.issues.list_templates()
|
|
348
|
+
assert len(items) == 1
|
|
349
|
+
assert items[0].path == ".github/ISSUE_TEMPLATE/bug_report.md"
|
|
350
|
+
assert items[0].sha == "ghsha"
|
|
351
|
+
assert items[0].template_owner == "acme"
|
|
352
|
+
assert items[0].template_repo == "proj"
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def test_get_template_from_dot_github_path(sync_client_factory):
|
|
356
|
+
path = ".github/PULL_REQUEST_TEMPLATE/default.md"
|
|
357
|
+
|
|
358
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
359
|
+
p = request.url.path
|
|
360
|
+
stub = _repo_metadata_nonfork_stub(request, p)
|
|
361
|
+
if stub is not None:
|
|
362
|
+
return stub
|
|
363
|
+
if p == "/api/v5/repos/acme/proj" and request.method == "GET" and "contents" not in p and "raw" not in p:
|
|
364
|
+
return httpx.Response(200, json={"fork": False})
|
|
365
|
+
if p == f"/api/v5/repos/acme/proj/raw/{path}":
|
|
366
|
+
return httpx.Response(200, content=b"github pr body")
|
|
367
|
+
raise AssertionError(f"unexpected {request.method} {p}")
|
|
368
|
+
|
|
369
|
+
client, _ = sync_client_factory(handler, owner="acme", repo="proj")
|
|
370
|
+
text = client.pulls.get_template(path=path)
|
|
371
|
+
assert text == "github pr body"
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"""Shared constant values for the GitCode SDK."""
|
|
2
|
-
|
|
3
|
-
DEFAULT_BASE_URL = "https://api.gitcode.com/api/v5"
|
|
4
|
-
DEFAULT_TIMEOUT = 30.0
|
|
5
|
-
DEFAULT_TOKEN_ENV = "GITCODE_ACCESS_TOKEN"
|
|
6
|
-
DEFAULT_CA_ENV = "GITCODE_CA_BUNDLE"
|
|
7
|
-
|
|
8
|
-
__all__ = ["DEFAULT_BASE_URL", "DEFAULT_TIMEOUT", "DEFAULT_TOKEN_ENV", "DEFAULT_CA_ENV"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.2.18
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|